2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <subdev/bios.h>
25 #include <subdev/bios/bit.h>
26 #include <subdev/bios/disp.h>
29 nvbios_disp_table(struct nvkm_bios
*bios
,
30 u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
, u8
*sub
)
34 if (!bit_entry(bios
, 'U', &U
)) {
36 u16 data
= nvbios_rd16(bios
, U
.offset
);
38 *ver
= nvbios_rd08(bios
, data
+ 0x00);
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);
59 nvbios_disp_entry(struct nvkm_bios
*bios
, u8 idx
, u8
*ver
, u8
*len
, u8
*sub
)
62 u16 data
= nvbios_disp_table(bios
, ver
, &hdr
, &cnt
, len
, sub
);
63 if (data
&& idx
< cnt
)
64 return data
+ hdr
+ (idx
* *len
);
70 nvbios_disp_parse(struct nvkm_bios
*bios
, u8 idx
, u8
*ver
, u8
*len
, u8
*sub
,
71 struct nvbios_disp
*info
)
73 u16 data
= nvbios_disp_entry(bios
, idx
, ver
, len
, sub
);
74 if (data
&& *len
>= 2) {
75 info
->data
= nvbios_rd16(bios
, data
+ 0);
82 nvbios_outp_entry(struct nvkm_bios
*bios
, u8 idx
,
83 u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
)
85 struct nvbios_disp info
;
86 u16 data
= nvbios_disp_parse(bios
, idx
, ver
, len
, hdr
, &info
);
88 *cnt
= nvbios_rd08(bios
, info
.data
+ 0x05);
96 nvbios_outp_parse(struct nvkm_bios
*bios
, u8 idx
,
97 u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
, struct nvbios_outp
*info
)
99 u16 data
= nvbios_outp_entry(bios
, idx
, ver
, hdr
, cnt
, len
);
100 if (data
&& *hdr
>= 0x0a) {
101 info
->type
= nvbios_rd16(bios
, data
+ 0x00);
102 info
->mask
= nvbios_rd32(bios
, data
+ 0x02);
103 if (*ver
<= 0x20) /* match any link */
104 info
->mask
|= 0x00c0;
105 info
->script
[0] = nvbios_rd16(bios
, data
+ 0x06);
106 info
->script
[1] = nvbios_rd16(bios
, data
+ 0x08);
107 info
->script
[2] = 0x0000;
109 info
->script
[2] = nvbios_rd16(bios
, data
+ 0x0a);
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
)
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
)
130 nvbios_ocfg_entry(struct nvkm_bios
*bios
, u16 outp
, u8 idx
,
131 u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
)
134 return outp
+ *hdr
+ (idx
* *len
);
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
)
142 u16 data
= nvbios_ocfg_entry(bios
, outp
, idx
, ver
, hdr
, cnt
, len
);
144 info
->proto
= nvbios_rd08(bios
, data
+ 0x00);
145 info
->flags
= nvbios_rd16(bios
, data
+ 0x01);
146 info
->clkcmp
[0] = nvbios_rd16(bios
, data
+ 0x02);
147 info
->clkcmp
[1] = nvbios_rd16(bios
, data
+ 0x04);
153 nvbios_ocfg_match(struct nvkm_bios
*bios
, u16 outp
, u8 proto
, u8 flags
,
154 u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
, struct nvbios_ocfg
*info
)
157 while ((data
= nvbios_ocfg_parse(bios
, outp
, idx
++, ver
, hdr
, cnt
, len
, info
))) {
158 if ((info
->proto
== proto
|| info
->proto
== 0xff) &&
159 (info
->flags
== flags
))
166 nvbios_oclk_match(struct nvkm_bios
*bios
, u16 cmp
, u32 khz
)
169 if (khz
/ 10 >= nvbios_rd16(bios
, cmp
+ 0x00))
170 return nvbios_rd16(bios
, cmp
+ 0x02);