Commit | Line | Data |
---|---|---|
b6caea50 BS |
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 | */ | |
b6caea50 BS |
24 | #include <subdev/bios.h> |
25 | #include <subdev/bios/bit.h> | |
26 | #include <subdev/bios/disp.h> | |
27 | ||
28 | u16 | |
d390b480 | 29 | nvbios_disp_table(struct nvkm_bios *bios, |
b6caea50 BS |
30 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *sub) |
31 | { | |
32 | struct bit_entry U; | |
33 | ||
34 | if (!bit_entry(bios, 'U', &U)) { | |
35 | if (U.version == 1) { | |
7f5f518f | 36 | u16 data = nvbios_rd16(bios, U.offset); |
b6caea50 | 37 | if (data) { |
7f5f518f | 38 | *ver = nvbios_rd08(bios, data + 0x00); |
b6caea50 BS |
39 | switch (*ver) { |
40 | case 0x20: | |
41 | case 0x21: | |
17187c81 | 42 | case 0x22: |
7f5f518f BS |
43 | *hdr = nvbios_rd08(bios, data + 0x01); |
44 | *len = nvbios_rd08(bios, data + 0x02); | |
45 | *cnt = nvbios_rd08(bios, data + 0x03); | |
46 | *sub = nvbios_rd08(bios, data + 0x04); | |
b6caea50 BS |
47 | return data; |
48 | default: | |
49 | break; | |
50 | } | |
51 | } | |
52 | } | |
53 | } | |
54 | ||
55 | return 0x0000; | |
56 | } | |
57 | ||
58 | u16 | |
d390b480 | 59 | nvbios_disp_entry(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, u8 *sub) |
b6caea50 BS |
60 | { |
61 | u8 hdr, cnt; | |
62 | u16 data = nvbios_disp_table(bios, ver, &hdr, &cnt, len, sub); | |
63 | if (data && idx < cnt) | |
64 | return data + hdr + (idx * *len); | |
65 | *ver = 0x00; | |
66 | return 0x0000; | |
67 | } | |
68 | ||
69 | u16 | |
d390b480 | 70 | nvbios_disp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len, u8 *sub, |
b6caea50 BS |
71 | struct nvbios_disp *info) |
72 | { | |
73 | u16 data = nvbios_disp_entry(bios, idx, ver, len, sub); | |
74 | if (data && *len >= 2) { | |
7f5f518f | 75 | info->data = nvbios_rd16(bios, data + 0); |
b6caea50 BS |
76 | return data; |
77 | } | |
78 | return 0x0000; | |
79 | } | |
80 | ||
81 | u16 | |
d390b480 | 82 | nvbios_outp_entry(struct nvkm_bios *bios, u8 idx, |
b6caea50 BS |
83 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
84 | { | |
85 | struct nvbios_disp info; | |
86 | u16 data = nvbios_disp_parse(bios, idx, ver, len, hdr, &info); | |
87 | if (data) { | |
7f5f518f | 88 | *cnt = nvbios_rd08(bios, info.data + 0x05); |
b6caea50 BS |
89 | *len = 0x06; |
90 | data = info.data; | |
91 | } | |
92 | return data; | |
93 | } | |
94 | ||
95 | u16 | |
d390b480 BS |
96 | nvbios_outp_parse(struct nvkm_bios *bios, u8 idx, |
97 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *info) | |
b6caea50 BS |
98 | { |
99 | u16 data = nvbios_outp_entry(bios, idx, ver, hdr, cnt, len); | |
100 | if (data && *hdr >= 0x0a) { | |
7f5f518f BS |
101 | info->type = nvbios_rd16(bios, data + 0x00); |
102 | info->mask = nvbios_rd32(bios, data + 0x02); | |
b6caea50 BS |
103 | if (*ver <= 0x20) /* match any link */ |
104 | info->mask |= 0x00c0; | |
7f5f518f BS |
105 | info->script[0] = nvbios_rd16(bios, data + 0x06); |
106 | info->script[1] = nvbios_rd16(bios, data + 0x08); | |
b6caea50 BS |
107 | info->script[2] = 0x0000; |
108 | if (*hdr >= 0x0c) | |
7f5f518f | 109 | info->script[2] = nvbios_rd16(bios, data + 0x0a); |
b6caea50 BS |
110 | return data; |
111 | } | |
112 | return 0x0000; | |
113 | } | |
114 | ||
115 | u16 | |
d390b480 BS |
116 | nvbios_outp_match(struct nvkm_bios *bios, u16 type, u16 mask, |
117 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *info) | |
b6caea50 BS |
118 | { |
119 | u16 data, idx = 0; | |
120 | while ((data = nvbios_outp_parse(bios, idx++, ver, hdr, cnt, len, info)) || *ver) { | |
121 | if (data && info->type == type) { | |
122 | if ((info->mask & mask) == mask) | |
123 | break; | |
124 | } | |
125 | } | |
126 | return data; | |
127 | } | |
128 | ||
129 | u16 | |
d390b480 | 130 | nvbios_ocfg_entry(struct nvkm_bios *bios, u16 outp, u8 idx, |
b6caea50 BS |
131 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
132 | { | |
133 | if (idx < *cnt) | |
134 | return outp + *hdr + (idx * *len); | |
135 | return 0x0000; | |
136 | } | |
137 | ||
138 | u16 | |
d390b480 BS |
139 | nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx, |
140 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info) | |
b6caea50 BS |
141 | { |
142 | u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len); | |
143 | if (data) { | |
7f5f518f BS |
144 | info->match = nvbios_rd16(bios, data + 0x00); |
145 | info->clkcmp[0] = nvbios_rd16(bios, data + 0x02); | |
146 | info->clkcmp[1] = nvbios_rd16(bios, data + 0x04); | |
b6caea50 BS |
147 | } |
148 | return data; | |
149 | } | |
150 | ||
151 | u16 | |
d390b480 BS |
152 | nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u16 type, |
153 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info) | |
b6caea50 BS |
154 | { |
155 | u16 data, idx = 0; | |
156 | while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) { | |
157 | if (info->match == type) | |
158 | break; | |
159 | } | |
160 | return data; | |
161 | } | |
162 | ||
163 | u16 | |
d390b480 | 164 | nvbios_oclk_match(struct nvkm_bios *bios, u16 cmp, u32 khz) |
b6caea50 BS |
165 | { |
166 | while (cmp) { | |
7f5f518f BS |
167 | if (khz / 10 >= nvbios_rd16(bios, cmp + 0x00)) |
168 | return nvbios_rd16(bios, cmp + 0x02); | |
b6caea50 BS |
169 | cmp += 0x04; |
170 | } | |
171 | return 0x0000; | |
172 | } |