diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-01 21:02:47 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-28 18:57:43 -0500 |
commit | b6caea505879c4a606cf364442fd1f06f6c40e30 (patch) | |
tree | 88b8e1c32f0a3addf120f495d95366c88037542e | |
parent | b5a794b0f1fdf17b92ed4f8a63ed23c7a3325841 (diff) |
drm/nouveau/bios: implement BIT 'U' table (and subtable) parsing in core
This will, in the near future, replace what's currently in the DRM
nouveau_bios.c code.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/bios/disp.h | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bios/disp.c | 178 |
3 files changed, 227 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 4219dc5e2f17..2ca1d39d5027 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -29,6 +29,7 @@ nouveau-y += core/subdev/bios/base.o | |||
29 | nouveau-y += core/subdev/bios/bit.o | 29 | nouveau-y += core/subdev/bios/bit.o |
30 | nouveau-y += core/subdev/bios/conn.o | 30 | nouveau-y += core/subdev/bios/conn.o |
31 | nouveau-y += core/subdev/bios/dcb.o | 31 | nouveau-y += core/subdev/bios/dcb.o |
32 | nouveau-y += core/subdev/bios/disp.o | ||
32 | nouveau-y += core/subdev/bios/dp.o | 33 | nouveau-y += core/subdev/bios/dp.o |
33 | nouveau-y += core/subdev/bios/extdev.o | 34 | nouveau-y += core/subdev/bios/extdev.o |
34 | nouveau-y += core/subdev/bios/gpio.o | 35 | nouveau-y += core/subdev/bios/gpio.o |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/disp.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/disp.h new file mode 100644 index 000000000000..c35937e2f6a4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/disp.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef __NVBIOS_DISP_H__ | ||
2 | #define __NVBIOS_DISP_H__ | ||
3 | |||
4 | u16 nvbios_disp_table(struct nouveau_bios *, | ||
5 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *sub); | ||
6 | |||
7 | struct nvbios_disp { | ||
8 | u16 data; | ||
9 | }; | ||
10 | |||
11 | u16 nvbios_disp_entry(struct nouveau_bios *, u8 idx, | ||
12 | u8 *ver, u8 *hdr__, u8 *sub); | ||
13 | u16 nvbios_disp_parse(struct nouveau_bios *, u8 idx, | ||
14 | u8 *ver, u8 *hdr__, u8 *sub, | ||
15 | struct nvbios_disp *); | ||
16 | |||
17 | struct nvbios_outp { | ||
18 | u16 type; | ||
19 | u16 mask; | ||
20 | u16 script[3]; | ||
21 | }; | ||
22 | |||
23 | u16 nvbios_outp_entry(struct nouveau_bios *, u8 idx, | ||
24 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
25 | u16 nvbios_outp_parse(struct nouveau_bios *, u8 idx, | ||
26 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
27 | struct nvbios_outp *); | ||
28 | u16 nvbios_outp_match(struct nouveau_bios *, u16 type, u16 mask, | ||
29 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
30 | struct nvbios_outp *); | ||
31 | |||
32 | |||
33 | struct nvbios_ocfg { | ||
34 | u16 match; | ||
35 | u16 clkcmp[2]; | ||
36 | }; | ||
37 | |||
38 | u16 nvbios_ocfg_entry(struct nouveau_bios *, u16 outp, u8 idx, | ||
39 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | ||
40 | u16 nvbios_ocfg_parse(struct nouveau_bios *, u16 outp, u8 idx, | ||
41 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
42 | struct nvbios_ocfg *); | ||
43 | u16 nvbios_ocfg_match(struct nouveau_bios *, u16 outp, u16 type, | ||
44 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
45 | struct nvbios_ocfg *); | ||
46 | u16 nvbios_oclk_match(struct nouveau_bios *, u16 cmp, u32 khz); | ||
47 | |||
48 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/disp.c b/drivers/gpu/drm/nouveau/core/subdev/bios/disp.c new file mode 100644 index 000000000000..7f16e52d9bea --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/disp.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Copyright 2012 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/disp.h> | ||
28 | |||
29 | u16 | ||
30 | nvbios_disp_table(struct nouveau_bios *bios, | ||
31 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *sub) | ||
32 | { | ||
33 | struct bit_entry U; | ||
34 | |||
35 | if (!bit_entry(bios, 'U', &U)) { | ||
36 | if (U.version == 1) { | ||
37 | u16 data = nv_ro16(bios, U.offset); | ||
38 | if (data) { | ||
39 | *ver = nv_ro08(bios, data + 0x00); | ||
40 | switch (*ver) { | ||
41 | case 0x20: | ||
42 | case 0x21: | ||
43 | *hdr = nv_ro08(bios, data + 0x01); | ||
44 | *len = nv_ro08(bios, data + 0x02); | ||
45 | *cnt = nv_ro08(bios, data + 0x03); | ||
46 | *sub = nv_ro08(bios, data + 0x04); | ||
47 | return data; | ||
48 | default: | ||
49 | break; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return 0x0000; | ||
56 | } | ||
57 | |||
58 | u16 | ||
59 | nvbios_disp_entry(struct nouveau_bios *bios, u8 idx, | ||
60 | u8 *ver, u8 *len, u8 *sub) | ||
61 | { | ||
62 | u8 hdr, cnt; | ||
63 | u16 data = nvbios_disp_table(bios, ver, &hdr, &cnt, len, sub); | ||
64 | if (data && idx < cnt) | ||
65 | return data + hdr + (idx * *len); | ||
66 | *ver = 0x00; | ||
67 | return 0x0000; | ||
68 | } | ||
69 | |||
70 | u16 | ||
71 | nvbios_disp_parse(struct nouveau_bios *bios, u8 idx, | ||
72 | u8 *ver, u8 *len, u8 *sub, | ||
73 | struct nvbios_disp *info) | ||
74 | { | ||
75 | u16 data = nvbios_disp_entry(bios, idx, ver, len, sub); | ||
76 | if (data && *len >= 2) { | ||
77 | info->data = nv_ro16(bios, data + 0); | ||
78 | return data; | ||
79 | } | ||
80 | return 0x0000; | ||
81 | } | ||
82 | |||
83 | u16 | ||
84 | nvbios_outp_entry(struct nouveau_bios *bios, u8 idx, | ||
85 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||
86 | { | ||
87 | struct nvbios_disp info; | ||
88 | u16 data = nvbios_disp_parse(bios, idx, ver, len, hdr, &info); | ||
89 | if (data) { | ||
90 | *cnt = nv_ro08(bios, info.data + 0x05); | ||
91 | *len = 0x06; | ||
92 | data = info.data; | ||
93 | } | ||
94 | return data; | ||
95 | } | ||
96 | |||
97 | u16 | ||
98 | nvbios_outp_parse(struct nouveau_bios *bios, u8 idx, | ||
99 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
100 | struct nvbios_outp *info) | ||
101 | { | ||
102 | u16 data = nvbios_outp_entry(bios, idx, ver, hdr, cnt, len); | ||
103 | if (data && *hdr >= 0x0a) { | ||
104 | info->type = nv_ro16(bios, data + 0x00); | ||
105 | info->mask = nv_ro32(bios, data + 0x02); | ||
106 | if (*ver <= 0x20) /* match any link */ | ||
107 | info->mask |= 0x00c0; | ||
108 | info->script[0] = nv_ro16(bios, data + 0x06); | ||
109 | info->script[1] = nv_ro16(bios, data + 0x08); | ||
110 | info->script[2] = 0x0000; | ||
111 | if (*hdr >= 0x0c) | ||
112 | info->script[2] = nv_ro16(bios, data + 0x0a); | ||
113 | return data; | ||
114 | } | ||
115 | return 0x0000; | ||
116 | } | ||
117 | |||
118 | u16 | ||
119 | nvbios_outp_match(struct nouveau_bios *bios, u16 type, u16 mask, | ||
120 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
121 | struct nvbios_outp *info) | ||
122 | { | ||
123 | u16 data, idx = 0; | ||
124 | while ((data = nvbios_outp_parse(bios, idx++, ver, hdr, cnt, len, info)) || *ver) { | ||
125 | if (data && info->type == type) { | ||
126 | if ((info->mask & mask) == mask) | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | return data; | ||
131 | } | ||
132 | |||
133 | u16 | ||
134 | nvbios_ocfg_entry(struct nouveau_bios *bios, u16 outp, u8 idx, | ||
135 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||
136 | { | ||
137 | if (idx < *cnt) | ||
138 | return outp + *hdr + (idx * *len); | ||
139 | return 0x0000; | ||
140 | } | ||
141 | |||
142 | u16 | ||
143 | nvbios_ocfg_parse(struct nouveau_bios *bios, u16 outp, u8 idx, | ||
144 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
145 | struct nvbios_ocfg *info) | ||
146 | { | ||
147 | u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len); | ||
148 | if (data) { | ||
149 | info->match = nv_ro16(bios, data + 0x00); | ||
150 | info->clkcmp[0] = nv_ro16(bios, data + 0x02); | ||
151 | info->clkcmp[1] = nv_ro16(bios, data + 0x04); | ||
152 | } | ||
153 | return data; | ||
154 | } | ||
155 | |||
156 | u16 | ||
157 | nvbios_ocfg_match(struct nouveau_bios *bios, u16 outp, u16 type, | ||
158 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
159 | struct nvbios_ocfg *info) | ||
160 | { | ||
161 | u16 data, idx = 0; | ||
162 | while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) { | ||
163 | if (info->match == type) | ||
164 | break; | ||
165 | } | ||
166 | return data; | ||
167 | } | ||
168 | |||
169 | u16 | ||
170 | nvbios_oclk_match(struct nouveau_bios *bios, u16 cmp, u32 khz) | ||
171 | { | ||
172 | while (cmp) { | ||
173 | if (khz / 10 >= nv_ro16(bios, cmp + 0x00)) | ||
174 | return nv_ro16(bios, cmp + 0x02); | ||
175 | cmp += 0x04; | ||
176 | } | ||
177 | return 0x0000; | ||
178 | } | ||