dcb.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. */
  24. #include <subdev/bios.h>
  25. #include <subdev/bios/dcb.h>
  26. u16
  27. dcb_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
  28. {
  29. struct nvkm_subdev *subdev = &bios->subdev;
  30. struct nvkm_device *device = subdev->device;
  31. u16 dcb = 0x0000;
  32. if (device->card_type > NV_04)
  33. dcb = nvbios_rd16(bios, 0x36);
  34. if (!dcb) {
  35. nvkm_warn(subdev, "DCB table not found\n");
  36. return dcb;
  37. }
  38. *ver = nvbios_rd08(bios, dcb);
  39. if (*ver >= 0x42) {
  40. nvkm_warn(subdev, "DCB version 0x%02x unknown\n", *ver);
  41. return 0x0000;
  42. } else
  43. if (*ver >= 0x30) {
  44. if (nvbios_rd32(bios, dcb + 6) == 0x4edcbdcb) {
  45. *hdr = nvbios_rd08(bios, dcb + 1);
  46. *cnt = nvbios_rd08(bios, dcb + 2);
  47. *len = nvbios_rd08(bios, dcb + 3);
  48. return dcb;
  49. }
  50. } else
  51. if (*ver >= 0x20) {
  52. if (nvbios_rd32(bios, dcb + 4) == 0x4edcbdcb) {
  53. u16 i2c = nvbios_rd16(bios, dcb + 2);
  54. *hdr = 8;
  55. *cnt = (i2c - dcb) / 8;
  56. *len = 8;
  57. return dcb;
  58. }
  59. } else
  60. if (*ver >= 0x15) {
  61. if (!nvbios_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
  62. u16 i2c = nvbios_rd16(bios, dcb + 2);
  63. *hdr = 4;
  64. *cnt = (i2c - dcb) / 10;
  65. *len = 10;
  66. return dcb;
  67. }
  68. } else {
  69. /*
  70. * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but
  71. * always has the same single (crt) entry, even when tv-out
  72. * present, so the conclusion is this version cannot really
  73. * be used.
  74. *
  75. * v1.2 tables (some NV6/10, and NV15+) normally have the
  76. * same 5 entries, which are not specific to the card and so
  77. * no use.
  78. *
  79. * v1.2 does have an I2C table that read_dcb_i2c_table can
  80. * handle, but cards exist (nv11 in #14821) with a bad i2c
  81. * table pointer, so use the indices parsed in
  82. * parse_bmp_structure.
  83. *
  84. * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
  85. */
  86. nvkm_debug(subdev, "DCB contains no useful data\n");
  87. return 0x0000;
  88. }
  89. nvkm_warn(subdev, "DCB header validation failed\n");
  90. return 0x0000;
  91. }
  92. u16
  93. dcb_outp(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len)
  94. {
  95. u8 hdr, cnt;
  96. u16 dcb = dcb_table(bios, ver, &hdr, &cnt, len);
  97. if (dcb && idx < cnt)
  98. return dcb + hdr + (idx * *len);
  99. return 0x0000;
  100. }
  101. static inline u16
  102. dcb_outp_hasht(struct dcb_output *outp)
  103. {
  104. return (outp->extdev << 8) | (outp->location << 4) | outp->type;
  105. }
  106. static inline u16
  107. dcb_outp_hashm(struct dcb_output *outp)
  108. {
  109. return (outp->heads << 8) | (outp->link << 6) | outp->or;
  110. }
  111. u16
  112. dcb_outp_parse(struct nvkm_bios *bios, u8 idx, u8 *ver, u8 *len,
  113. struct dcb_output *outp)
  114. {
  115. u16 dcb = dcb_outp(bios, idx, ver, len);
  116. memset(outp, 0x00, sizeof(*outp));
  117. if (dcb) {
  118. if (*ver >= 0x20) {
  119. u32 conn = nvbios_rd32(bios, dcb + 0x00);
  120. outp->or = (conn & 0x0f000000) >> 24;
  121. outp->location = (conn & 0x00300000) >> 20;
  122. outp->bus = (conn & 0x000f0000) >> 16;
  123. outp->connector = (conn & 0x0000f000) >> 12;
  124. outp->heads = (conn & 0x00000f00) >> 8;
  125. outp->i2c_index = (conn & 0x000000f0) >> 4;
  126. outp->type = (conn & 0x0000000f);
  127. outp->link = 0;
  128. } else {
  129. dcb = 0x0000;
  130. }
  131. if (*ver >= 0x40) {
  132. u32 conf = nvbios_rd32(bios, dcb + 0x04);
  133. switch (outp->type) {
  134. case DCB_OUTPUT_DP:
  135. switch (conf & 0x00e00000) {
  136. case 0x00000000: /* 1.62 */
  137. outp->dpconf.link_bw = 0x06;
  138. break;
  139. case 0x00200000: /* 2.7 */
  140. outp->dpconf.link_bw = 0x0a;
  141. break;
  142. case 0x00400000: /* 5.4 */
  143. outp->dpconf.link_bw = 0x14;
  144. break;
  145. case 0x00600000: /* 8.1 */
  146. default:
  147. outp->dpconf.link_bw = 0x1e;
  148. break;
  149. }
  150. switch ((conf & 0x0f000000) >> 24) {
  151. case 0xf:
  152. case 0x4:
  153. outp->dpconf.link_nr = 4;
  154. break;
  155. case 0x3:
  156. case 0x2:
  157. outp->dpconf.link_nr = 2;
  158. break;
  159. case 0x1:
  160. default:
  161. outp->dpconf.link_nr = 1;
  162. break;
  163. }
  164. /* fall-through... */
  165. case DCB_OUTPUT_TMDS:
  166. case DCB_OUTPUT_LVDS:
  167. outp->link = (conf & 0x00000030) >> 4;
  168. outp->sorconf.link = outp->link; /*XXX*/
  169. outp->extdev = 0x00;
  170. if (outp->location != 0)
  171. outp->extdev = (conf & 0x0000ff00) >> 8;
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. outp->hasht = dcb_outp_hasht(outp);
  178. outp->hashm = dcb_outp_hashm(outp);
  179. }
  180. return dcb;
  181. }
  182. u16
  183. dcb_outp_match(struct nvkm_bios *bios, u16 type, u16 mask,
  184. u8 *ver, u8 *len, struct dcb_output *outp)
  185. {
  186. u16 dcb, idx = 0;
  187. while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) {
  188. if ((dcb_outp_hasht(outp) & 0x00ff) == (type & 0x00ff)) {
  189. if ((dcb_outp_hashm(outp) & mask) == mask)
  190. break;
  191. }
  192. }
  193. return dcb;
  194. }
  195. int
  196. dcb_outp_foreach(struct nvkm_bios *bios, void *data,
  197. int (*exec)(struct nvkm_bios *, void *, int, u16))
  198. {
  199. int ret, idx = -1;
  200. u8 ver, len;
  201. u16 outp;
  202. while ((outp = dcb_outp(bios, ++idx, &ver, &len))) {
  203. if (nvbios_rd32(bios, outp) == 0x00000000)
  204. break; /* seen on an NV11 with DCB v1.5 */
  205. if (nvbios_rd32(bios, outp) == 0xffffffff)
  206. break; /* seen on an NV17 with DCB v2.0 */
  207. if (nvbios_rd08(bios, outp) == DCB_OUTPUT_UNUSED)
  208. continue;
  209. if (nvbios_rd08(bios, outp) == DCB_OUTPUT_EOL)
  210. break;
  211. ret = exec(bios, data, idx, outp);
  212. if (ret)
  213. return ret;
  214. }
  215. return 0;
  216. }