diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-12-06 19:09:17 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-12-23 07:59:27 -0500 |
commit | d2bcea686f21e11415828fcca21a4eb200c6251f (patch) | |
tree | ec7877a2733c2ae117c81cac7af3123858d07696 /drivers/gpu/drm/nouveau | |
parent | caba557020d1e7cbb0dd21811e453589fb51ba53 (diff) |
drm/nouveau/bios: update gpio parsing apis to match current design
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | 128 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | 4 |
5 files changed, 90 insertions, 61 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 2bf178082a36..e6563b5cb08e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h | |||
@@ -25,9 +25,11 @@ struct dcb_gpio_func { | |||
25 | u8 param; | 25 | u8 param; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | u16 dcb_gpio_table(struct nouveau_bios *); | 28 | u16 dcb_gpio_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); |
29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver); | 29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len); |
30 | int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, | 30 | u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len, |
31 | struct dcb_gpio_func *); | 31 | struct dcb_gpio_func *); |
32 | u16 dcb_gpio_match(struct nouveau_bios *, int idx, u8 func, u8 line, | ||
33 | u8 *ver, u8 *len, struct dcb_gpio_func *); | ||
32 | 34 | ||
33 | #endif | 35 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index c90d4aa3ae4f..c84e93fa6d95 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | |||
@@ -27,84 +27,105 @@ | |||
27 | #include <subdev/bios/gpio.h> | 27 | #include <subdev/bios/gpio.h> |
28 | 28 | ||
29 | u16 | 29 | u16 |
30 | dcb_gpio_table(struct nouveau_bios *bios) | 30 | dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
31 | { | 31 | { |
32 | u8 ver, hdr, cnt, len; | 32 | u16 data = 0x0000; |
33 | u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); | 33 | u16 dcb = dcb_table(bios, ver, hdr, cnt, len); |
34 | if (dcb) { | 34 | if (dcb) { |
35 | if (ver >= 0x30 && hdr >= 0x0c) | 35 | if (*ver >= 0x30 && *hdr >= 0x0c) |
36 | return nv_ro16(bios, dcb + 0x0a); | 36 | data = nv_ro16(bios, dcb + 0x0a); |
37 | if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) | 37 | else |
38 | return nv_ro16(bios, dcb - 0x0f); | 38 | if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) |
39 | data = nv_ro16(bios, dcb - 0x0f); | ||
40 | |||
41 | if (data) { | ||
42 | *ver = nv_ro08(bios, data + 0x00); | ||
43 | if (*ver < 0x30) { | ||
44 | *hdr = 3; | ||
45 | *cnt = nv_ro08(bios, data + 0x02); | ||
46 | *len = nv_ro08(bios, data + 0x01); | ||
47 | } else | ||
48 | if (*ver <= 0x41) { | ||
49 | *hdr = nv_ro08(bios, data + 0x01); | ||
50 | *cnt = nv_ro08(bios, data + 0x02); | ||
51 | *len = nv_ro08(bios, data + 0x03); | ||
52 | } else { | ||
53 | data = 0x0000; | ||
54 | } | ||
55 | } | ||
39 | } | 56 | } |
40 | return 0x0000; | 57 | return data; |
41 | } | 58 | } |
42 | 59 | ||
43 | u16 | 60 | u16 |
44 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) | 61 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) |
45 | { | 62 | { |
46 | u16 gpio = dcb_gpio_table(bios); | 63 | u8 hdr, cnt; |
47 | if (gpio) { | 64 | u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; |
48 | *ver = nv_ro08(bios, gpio); | 65 | if (gpio && ent < cnt) |
49 | if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) | 66 | return gpio + hdr + (ent * *len); |
50 | return gpio + 3 + (ent * nv_ro08(bios, gpio + 1)); | ||
51 | else if (ent < nv_ro08(bios, gpio + 2)) | ||
52 | return gpio + nv_ro08(bios, gpio + 1) + | ||
53 | (ent * nv_ro08(bios, gpio + 3)); | ||
54 | } | ||
55 | return 0x0000; | 67 | return 0x0000; |
56 | } | 68 | } |
57 | 69 | ||
58 | int | 70 | u16 |
59 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | 71 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len, |
60 | struct dcb_gpio_func *gpio) | 72 | struct dcb_gpio_func *gpio) |
61 | { | 73 | { |
62 | u8 ver, hdr, cnt, len; | 74 | u16 data = dcb_gpio_entry(bios, idx, ent, ver, len); |
63 | u16 entry; | 75 | if (data) { |
64 | int i = -1; | 76 | if (*ver < 0x40) { |
65 | 77 | u16 info = nv_ro16(bios, data); | |
66 | while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) { | ||
67 | if (ver < 0x40) { | ||
68 | u16 data = nv_ro16(bios, entry); | ||
69 | *gpio = (struct dcb_gpio_func) { | 78 | *gpio = (struct dcb_gpio_func) { |
70 | .line = (data & 0x001f) >> 0, | 79 | .line = (info & 0x001f) >> 0, |
71 | .func = (data & 0x07e0) >> 5, | 80 | .func = (info & 0x07e0) >> 5, |
72 | .log[0] = (data & 0x1800) >> 11, | 81 | .log[0] = (info & 0x1800) >> 11, |
73 | .log[1] = (data & 0x6000) >> 13, | 82 | .log[1] = (info & 0x6000) >> 13, |
74 | .param = !!(data & 0x8000), | 83 | .param = !!(info & 0x8000), |
75 | }; | 84 | }; |
76 | } else | 85 | } else |
77 | if (ver < 0x41) { | 86 | if (*ver < 0x41) { |
78 | u32 data = nv_ro32(bios, entry); | 87 | u32 info = nv_ro32(bios, data); |
79 | *gpio = (struct dcb_gpio_func) { | 88 | *gpio = (struct dcb_gpio_func) { |
80 | .line = (data & 0x0000001f) >> 0, | 89 | .line = (info & 0x0000001f) >> 0, |
81 | .func = (data & 0x0000ff00) >> 8, | 90 | .func = (info & 0x0000ff00) >> 8, |
82 | .log[0] = (data & 0x18000000) >> 27, | 91 | .log[0] = (info & 0x18000000) >> 27, |
83 | .log[1] = (data & 0x60000000) >> 29, | 92 | .log[1] = (info & 0x60000000) >> 29, |
84 | .param = !!(data & 0x80000000), | 93 | .param = !!(info & 0x80000000), |
85 | }; | 94 | }; |
86 | } else { | 95 | } else { |
87 | u32 data = nv_ro32(bios, entry + 0); | 96 | u32 info = nv_ro32(bios, data + 0); |
88 | u8 data1 = nv_ro32(bios, entry + 4); | 97 | u8 info1 = nv_ro32(bios, data + 4); |
89 | *gpio = (struct dcb_gpio_func) { | 98 | *gpio = (struct dcb_gpio_func) { |
90 | .line = (data & 0x0000003f) >> 0, | 99 | .line = (info & 0x0000003f) >> 0, |
91 | .func = (data & 0x0000ff00) >> 8, | 100 | .func = (info & 0x0000ff00) >> 8, |
92 | .log[0] = (data1 & 0x30) >> 4, | 101 | .log[0] = (info1 & 0x30) >> 4, |
93 | .log[1] = (data1 & 0xc0) >> 6, | 102 | .log[1] = (info1 & 0xc0) >> 6, |
94 | .param = !!(data & 0x80000000), | 103 | .param = !!(info & 0x80000000), |
95 | }; | 104 | }; |
96 | } | 105 | } |
106 | } | ||
107 | |||
108 | return data; | ||
109 | } | ||
97 | 110 | ||
111 | u16 | ||
112 | dcb_gpio_match(struct nouveau_bios *bios, int idx, u8 func, u8 line, | ||
113 | u8 *ver, u8 *len, struct dcb_gpio_func *gpio) | ||
114 | { | ||
115 | u8 hdr, cnt, i = 0; | ||
116 | u16 data; | ||
117 | |||
118 | while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) { | ||
98 | if ((line == 0xff || line == gpio->line) && | 119 | if ((line == 0xff || line == gpio->line) && |
99 | (func == 0xff || func == gpio->func)) | 120 | (func == 0xff || func == gpio->func)) |
100 | return 0; | 121 | return data; |
101 | } | 122 | } |
102 | 123 | ||
103 | /* DCB 2.2, fixed TVDAC GPIO data */ | 124 | /* DCB 2.2, fixed TVDAC GPIO data */ |
104 | if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) { | 125 | if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) { |
105 | if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) { | 126 | if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) { |
106 | u8 conf = nv_ro08(bios, entry - 5); | 127 | u8 conf = nv_ro08(bios, data - 5); |
107 | u8 addr = nv_ro08(bios, entry - 4); | 128 | u8 addr = nv_ro08(bios, data - 4); |
108 | if (conf & 0x01) { | 129 | if (conf & 0x01) { |
109 | *gpio = (struct dcb_gpio_func) { | 130 | *gpio = (struct dcb_gpio_func) { |
110 | .func = DCB_GPIO_TVDAC0, | 131 | .func = DCB_GPIO_TVDAC0, |
@@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | |||
112 | .log[0] = !!(conf & 0x02), | 133 | .log[0] = !!(conf & 0x02), |
113 | .log[1] = !(conf & 0x02), | 134 | .log[1] = !(conf & 0x02), |
114 | }; | 135 | }; |
115 | return 0; | 136 | *ver = 0x00; |
137 | return data; | ||
116 | } | 138 | } |
117 | } | 139 | } |
118 | } | 140 | } |
119 | 141 | ||
120 | return -EINVAL; | 142 | return 0x0000; |
121 | } | 143 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index acf818c58bf0..39f267c3241e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | |||
@@ -43,10 +43,15 @@ static int | |||
43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, | 43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, |
44 | struct dcb_gpio_func *func) | 44 | struct dcb_gpio_func *func) |
45 | { | 45 | { |
46 | struct nouveau_bios *bios = nouveau_bios(gpio); | ||
47 | u8 ver, len; | ||
48 | u16 data; | ||
49 | |||
46 | if (line == 0xff && tag == 0xff) | 50 | if (line == 0xff && tag == 0xff) |
47 | return -EINVAL; | 51 | return -EINVAL; |
48 | 52 | ||
49 | if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func)) | 53 | data = dcb_gpio_match(bios, idx, tag, line, &ver, &len, func); |
54 | if (data) | ||
50 | return 0; | 55 | return 0; |
51 | 56 | ||
52 | /* Apple iMac G4 NV18 */ | 57 | /* Apple iMac G4 NV18 */ |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index f3502c961cd9..da2341392ced 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | |||
@@ -33,11 +33,11 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) | |||
33 | { | 33 | { |
34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
35 | struct nv50_gpio_priv *priv = (void *)gpio; | 35 | struct nv50_gpio_priv *priv = (void *)gpio; |
36 | u8 ver, len; | ||
36 | u16 entry; | 37 | u16 entry; |
37 | u8 ver; | ||
38 | int ent = -1; | 38 | int ent = -1; |
39 | 39 | ||
40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
41 | static const u32 regs[] = { 0xe100, 0xe28c }; | 41 | static const u32 regs[] = { 0xe100, 0xe28c }; |
42 | u32 data = nv_ro32(bios, entry); | 42 | u32 data = nv_ro32(bios, entry); |
43 | u8 line = (data & 0x0000001f); | 43 | u8 line = (data & 0x0000001f); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 8d18fcad26e0..cda607f24230 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | |||
@@ -33,11 +33,11 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) | |||
33 | { | 33 | { |
34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
35 | struct nvd0_gpio_priv *priv = (void *)gpio; | 35 | struct nvd0_gpio_priv *priv = (void *)gpio; |
36 | u8 ver, len; | ||
36 | u16 entry; | 37 | u16 entry; |
37 | u8 ver; | ||
38 | int ent = -1; | 38 | int ent = -1; |
39 | 39 | ||
40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
41 | u32 data = nv_ro32(bios, entry); | 41 | u32 data = nv_ro32(bios, entry); |
42 | u8 line = (data & 0x0000003f); | 42 | u8 line = (data & 0x0000003f); |
43 | u8 defs = !!(data & 0x00000080); | 43 | u8 defs = !!(data & 0x00000080); |