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/dcb.h>
26 #include <subdev/bios/gpio.h>
27 #include <subdev/bios/xpio.h>
30 dcb_gpio_table(struct nvkm_bios
*bios
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
)
33 u16 dcb
= dcb_table(bios
, ver
, hdr
, cnt
, len
);
35 if (*ver
>= 0x30 && *hdr
>= 0x0c)
36 data
= nvbios_rd16(bios
, dcb
+ 0x0a);
38 if (*ver
>= 0x22 && nvbios_rd08(bios
, dcb
- 1) >= 0x13)
39 data
= nvbios_rd16(bios
, dcb
- 0x0f);
42 *ver
= nvbios_rd08(bios
, data
+ 0x00);
45 *cnt
= nvbios_rd08(bios
, data
+ 0x02);
46 *len
= nvbios_rd08(bios
, data
+ 0x01);
49 *hdr
= nvbios_rd08(bios
, data
+ 0x01);
50 *cnt
= nvbios_rd08(bios
, data
+ 0x02);
51 *len
= nvbios_rd08(bios
, data
+ 0x03);
61 dcb_gpio_entry(struct nvkm_bios
*bios
, int idx
, int ent
, u8
*ver
, u8
*len
)
63 u8 hdr
, cnt
, xver
; /* use gpio version for xpio entry parsing */
67 gpio
= dcb_gpio_table(bios
, ver
, &hdr
, &cnt
, len
);
69 gpio
= dcb_xpio_table(bios
, idx
, &xver
, &hdr
, &cnt
, len
);
71 if (gpio
&& ent
< cnt
)
72 return gpio
+ hdr
+ (ent
* *len
);
78 dcb_gpio_parse(struct nvkm_bios
*bios
, int idx
, int ent
, u8
*ver
, u8
*len
,
79 struct dcb_gpio_func
*gpio
)
81 u16 data
= dcb_gpio_entry(bios
, idx
, ent
, ver
, len
);
84 u16 info
= nvbios_rd16(bios
, data
);
85 *gpio
= (struct dcb_gpio_func
) {
86 .line
= (info
& 0x001f) >> 0,
87 .func
= (info
& 0x07e0) >> 5,
88 .log
[0] = (info
& 0x1800) >> 11,
89 .log
[1] = (info
& 0x6000) >> 13,
90 .param
= !!(info
& 0x8000),
94 u32 info
= nvbios_rd32(bios
, data
);
95 *gpio
= (struct dcb_gpio_func
) {
96 .line
= (info
& 0x0000001f) >> 0,
97 .func
= (info
& 0x0000ff00) >> 8,
98 .log
[0] = (info
& 0x18000000) >> 27,
99 .log
[1] = (info
& 0x60000000) >> 29,
100 .param
= !!(info
& 0x80000000),
103 u32 info
= nvbios_rd32(bios
, data
+ 0);
104 u8 info1
= nvbios_rd32(bios
, data
+ 4);
105 *gpio
= (struct dcb_gpio_func
) {
106 .line
= (info
& 0x0000003f) >> 0,
107 .func
= (info
& 0x0000ff00) >> 8,
108 .log
[0] = (info1
& 0x30) >> 4,
109 .log
[1] = (info1
& 0xc0) >> 6,
110 .param
= !!(info
& 0x80000000),
119 dcb_gpio_match(struct nvkm_bios
*bios
, int idx
, u8 func
, u8 line
,
120 u8
*ver
, u8
*len
, struct dcb_gpio_func
*gpio
)
125 while ((data
= dcb_gpio_parse(bios
, idx
, i
++, ver
, len
, gpio
))) {
126 if ((line
== 0xff || line
== gpio
->line
) &&
127 (func
== 0xff || func
== gpio
->func
))
131 /* DCB 2.2, fixed TVDAC GPIO data */
132 if ((data
= dcb_table(bios
, ver
, &hdr
, &cnt
, len
))) {
133 if (*ver
>= 0x22 && *ver
< 0x30 && func
== DCB_GPIO_TVDAC0
) {
134 u8 conf
= nvbios_rd08(bios
, data
- 5);
135 u8 addr
= nvbios_rd08(bios
, data
- 4);
137 *gpio
= (struct dcb_gpio_func
) {
138 .func
= DCB_GPIO_TVDAC0
,
140 .log
[0] = !!(conf
& 0x02),
141 .log
[1] = !(conf
& 0x02),