0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <subdev/bios.h>
0025 #include <subdev/bios/dcb.h>
0026 #include <subdev/bios/gpio.h>
0027 #include <subdev/bios/xpio.h>
0028
0029 u16
0030 dcb_gpio_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
0031 {
0032 u16 data = 0x0000;
0033 u16 dcb = dcb_table(bios, ver, hdr, cnt, len);
0034 if (dcb) {
0035 if (*ver >= 0x30 && *hdr >= 0x0c)
0036 data = nvbios_rd16(bios, dcb + 0x0a);
0037 else
0038 if (*ver >= 0x22 && nvbios_rd08(bios, dcb - 1) >= 0x13)
0039 data = nvbios_rd16(bios, dcb - 0x0f);
0040
0041 if (data) {
0042 *ver = nvbios_rd08(bios, data + 0x00);
0043 if (*ver < 0x30) {
0044 *hdr = 3;
0045 *cnt = nvbios_rd08(bios, data + 0x02);
0046 *len = nvbios_rd08(bios, data + 0x01);
0047 } else
0048 if (*ver <= 0x41) {
0049 *hdr = nvbios_rd08(bios, data + 0x01);
0050 *cnt = nvbios_rd08(bios, data + 0x02);
0051 *len = nvbios_rd08(bios, data + 0x03);
0052 } else {
0053 data = 0x0000;
0054 }
0055 }
0056 }
0057 return data;
0058 }
0059
0060 u16
0061 dcb_gpio_entry(struct nvkm_bios *bios, int idx, int ent, u8 *ver, u8 *len)
0062 {
0063 u8 hdr, cnt, xver;
0064 u16 gpio;
0065
0066 if (!idx--)
0067 gpio = dcb_gpio_table(bios, ver, &hdr, &cnt, len);
0068 else
0069 gpio = dcb_xpio_table(bios, idx, &xver, &hdr, &cnt, len);
0070
0071 if (gpio && ent < cnt)
0072 return gpio + hdr + (ent * *len);
0073
0074 return 0x0000;
0075 }
0076
0077 u16
0078 dcb_gpio_parse(struct nvkm_bios *bios, int idx, int ent, u8 *ver, u8 *len,
0079 struct dcb_gpio_func *gpio)
0080 {
0081 u16 data = dcb_gpio_entry(bios, idx, ent, ver, len);
0082 if (data) {
0083 if (*ver < 0x40) {
0084 u16 info = nvbios_rd16(bios, data);
0085 *gpio = (struct dcb_gpio_func) {
0086 .line = (info & 0x001f) >> 0,
0087 .func = (info & 0x07e0) >> 5,
0088 .log[0] = (info & 0x1800) >> 11,
0089 .log[1] = (info & 0x6000) >> 13,
0090 .param = !!(info & 0x8000),
0091 };
0092 } else
0093 if (*ver < 0x41) {
0094 u32 info = nvbios_rd32(bios, data);
0095 *gpio = (struct dcb_gpio_func) {
0096 .line = (info & 0x0000001f) >> 0,
0097 .func = (info & 0x0000ff00) >> 8,
0098 .log[0] = (info & 0x18000000) >> 27,
0099 .log[1] = (info & 0x60000000) >> 29,
0100 .param = !!(info & 0x80000000),
0101 };
0102 } else {
0103 u32 info = nvbios_rd32(bios, data + 0);
0104 u8 info1 = nvbios_rd32(bios, data + 4);
0105 *gpio = (struct dcb_gpio_func) {
0106 .line = (info & 0x0000003f) >> 0,
0107 .func = (info & 0x0000ff00) >> 8,
0108 .log[0] = (info1 & 0x30) >> 4,
0109 .log[1] = (info1 & 0xc0) >> 6,
0110 .param = !!(info & 0x80000000),
0111 };
0112 }
0113 }
0114
0115 return data;
0116 }
0117
0118 u16
0119 dcb_gpio_match(struct nvkm_bios *bios, int idx, u8 func, u8 line,
0120 u8 *ver, u8 *len, struct dcb_gpio_func *gpio)
0121 {
0122 u8 hdr, cnt, i = 0;
0123 u16 data;
0124
0125 while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) {
0126 if ((line == 0xff || line == gpio->line) &&
0127 (func == 0xff || func == gpio->func))
0128 return data;
0129 }
0130
0131
0132 if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) {
0133 if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) {
0134 u8 conf = nvbios_rd08(bios, data - 5);
0135 u8 addr = nvbios_rd08(bios, data - 4);
0136 if (conf & 0x01) {
0137 *gpio = (struct dcb_gpio_func) {
0138 .func = DCB_GPIO_TVDAC0,
0139 .line = addr >> 4,
0140 .log[0] = !!(conf & 0x02),
0141 .log[1] = !(conf & 0x02),
0142 };
0143 *ver = 0x00;
0144 return data;
0145 }
0146 }
0147 }
0148
0149 return 0x0000;
0150 }