nouveau_mxm.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /*
  2. * Copyright 2011 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 <linux/acpi.h>
  25. #include "drmP.h"
  26. #include "nouveau_drv.h"
  27. #define MXM_DBG(dev, fmt, args...) NV_DEBUG((dev), "MXM: " fmt, ##args)
  28. #define MXM_MSG(dev, fmt, args...) NV_INFO((dev), "MXM: " fmt, ##args)
  29. static u8 *
  30. mxms_data(struct drm_device *dev)
  31. {
  32. struct drm_nouveau_private *dev_priv = dev->dev_private;
  33. return dev_priv->mxms;
  34. }
  35. static u16
  36. mxms_version(struct drm_device *dev)
  37. {
  38. u8 *mxms = mxms_data(dev);
  39. u16 version = (mxms[4] << 8) | mxms[5];
  40. switch (version ) {
  41. case 0x0200:
  42. case 0x0201:
  43. case 0x0300:
  44. return version;
  45. default:
  46. break;
  47. }
  48. MXM_DBG(dev, "unknown version %d.%d\n", mxms[4], mxms[5]);
  49. return 0x0000;
  50. }
  51. static u16
  52. mxms_headerlen(struct drm_device *dev)
  53. {
  54. return 8;
  55. }
  56. static u16
  57. mxms_structlen(struct drm_device *dev)
  58. {
  59. return *(u16 *)&mxms_data(dev)[6];
  60. }
  61. static bool
  62. mxms_checksum(struct drm_device *dev)
  63. {
  64. u16 size = mxms_headerlen(dev) + mxms_structlen(dev);
  65. u8 *mxms = mxms_data(dev), sum = 0;
  66. while (size--)
  67. sum += *mxms++;
  68. if (sum) {
  69. MXM_DBG(dev, "checksum invalid\n");
  70. return false;
  71. }
  72. return true;
  73. }
  74. static bool
  75. mxms_valid(struct drm_device *dev)
  76. {
  77. u8 *mxms = mxms_data(dev);
  78. if (*(u32 *)mxms != 0x5f4d584d) {
  79. MXM_DBG(dev, "signature invalid\n");
  80. return false;
  81. }
  82. if (!mxms_version(dev) || !mxms_checksum(dev))
  83. return false;
  84. return true;
  85. }
  86. static bool
  87. mxms_foreach(struct drm_device *dev, u8 types,
  88. bool (*exec)(struct drm_device *, u8 *, void *), void *info)
  89. {
  90. u8 *mxms = mxms_data(dev);
  91. u8 *desc = mxms + mxms_headerlen(dev);
  92. u8 *fini = desc + mxms_structlen(dev) - 1;
  93. while (desc < fini) {
  94. u8 type = desc[0] & 0x0f;
  95. u8 headerlen = 0;
  96. u8 recordlen = 0;
  97. u8 entries = 0;
  98. switch (type) {
  99. case 0: /* Output Device Structure */
  100. if (mxms_version(dev) >= 0x0300)
  101. headerlen = 8;
  102. else
  103. headerlen = 6;
  104. break;
  105. case 1: /* System Cooling Capability Structure */
  106. case 2: /* Thermal Structure */
  107. case 3: /* Input Power Structure */
  108. headerlen = 4;
  109. break;
  110. case 4: /* GPIO Device Structure */
  111. headerlen = 4;
  112. recordlen = 2;
  113. entries = (ROM32(desc[0]) & 0x01f00000) >> 20;
  114. break;
  115. case 5: /* Vendor Specific Structure */
  116. headerlen = 8;
  117. break;
  118. case 6: /* Backlight Control Structure */
  119. if (mxms_version(dev) >= 0x0300) {
  120. headerlen = 4;
  121. recordlen = 8;
  122. entries = (desc[1] & 0xf0) >> 4;
  123. } else {
  124. headerlen = 8;
  125. }
  126. break;
  127. case 7: /* Fan Control Structure */
  128. headerlen = 8;
  129. recordlen = 4;
  130. entries = desc[1] & 0x07;
  131. break;
  132. default:
  133. MXM_DBG(dev, "unknown descriptor type %d\n", type);
  134. return false;
  135. }
  136. if ((drm_debug & DRM_UT_DRIVER) && (exec == NULL)) {
  137. static const char * mxms_desc_name[] = {
  138. "ODS", "SCCS", "TS", "IPS",
  139. "GSD", "VSS", "BCS", "FCS",
  140. };
  141. u8 *dump = desc;
  142. int i, j;
  143. MXM_DBG(dev, "%4s: ", mxms_desc_name[type]);
  144. for (j = headerlen - 1; j >= 0; j--)
  145. printk("%02x", dump[j]);
  146. printk("\n");
  147. dump += headerlen;
  148. for (i = 0; i < entries; i++, dump += recordlen) {
  149. MXM_DBG(dev, " ");
  150. for (j = recordlen - 1; j >= 0; j--)
  151. printk("%02x", dump[j]);
  152. printk("\n");
  153. }
  154. }
  155. if (types & (1 << type)) {
  156. if (!exec(dev, desc, info))
  157. return false;
  158. }
  159. desc += headerlen + (entries * recordlen);
  160. }
  161. return true;
  162. }
  163. static u8 *
  164. mxm_table(struct drm_device *dev, u8 *size)
  165. {
  166. struct bit_entry x;
  167. if (bit_table(dev, 'x', &x)) {
  168. MXM_DBG(dev, "BIT 'x' table not present\n");
  169. return NULL;
  170. }
  171. if (x.version != 1 || x.length < 3) {
  172. MXM_MSG(dev, "BIT x table %d/%d unknown\n",
  173. x.version, x.length);
  174. return NULL;
  175. }
  176. *size = x.length;
  177. return x.data;
  178. }
  179. /* These map MXM v2.x digital connection values to the appropriate SOR/link,
  180. * hopefully they're correct for all boards within the same chipset...
  181. *
  182. * MXM v3.x VBIOS are nicer and provide pointers to these tables.
  183. */
  184. static u8 nv84_sor_map[16] = {
  185. 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31,
  186. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  187. };
  188. static u8 nv92_sor_map[16] = {
  189. 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31,
  190. 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  191. };
  192. static u8 nv94_sor_map[16] = {
  193. 0x00, 0x14, 0x24, 0x11, 0x34, 0x31, 0x11, 0x31,
  194. 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00
  195. };
  196. static u8 nv96_sor_map[16] = {
  197. 0x00, 0x14, 0x24, 0x00, 0x34, 0x00, 0x11, 0x31,
  198. 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00
  199. };
  200. static u8 nv98_sor_map[16] = {
  201. 0x00, 0x14, 0x12, 0x11, 0x00, 0x31, 0x11, 0x31,
  202. 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  203. };
  204. static u8
  205. mxm_sor_map(struct drm_device *dev, u8 conn)
  206. {
  207. struct drm_nouveau_private *dev_priv = dev->dev_private;
  208. u8 len, *mxm = mxm_table(dev, &len);
  209. if (mxm && len >= 6) {
  210. u8 *map = ROMPTR(dev, mxm[4]);
  211. if (map) {
  212. if (map[0] == 0x10) {
  213. if (conn < map[3])
  214. return map[map[1] + conn];
  215. return 0x00;
  216. }
  217. MXM_MSG(dev, "unknown sor map 0x%02x\n", map[0]);
  218. }
  219. }
  220. if (dev_priv->chipset == 0x84 || dev_priv->chipset == 0x86)
  221. return nv84_sor_map[conn];
  222. if (dev_priv->chipset == 0x92)
  223. return nv92_sor_map[conn];
  224. if (dev_priv->chipset == 0x94)
  225. return nv94_sor_map[conn];
  226. if (dev_priv->chipset == 0x96)
  227. return nv96_sor_map[conn];
  228. if (dev_priv->chipset == 0x98)
  229. return nv98_sor_map[conn];
  230. MXM_MSG(dev, "missing sor map\n");
  231. return 0x00;
  232. }
  233. static u8
  234. mxm_ddc_map(struct drm_device *dev, u8 port)
  235. {
  236. u8 len, *mxm = mxm_table(dev, &len);
  237. if (mxm && len >= 8) {
  238. u8 *map = ROMPTR(dev, mxm[6]);
  239. if (map) {
  240. if (map[0] == 0x10) {
  241. if (port < map[3])
  242. return map[map[1] + port];
  243. return 0x00;
  244. }
  245. MXM_MSG(dev, "unknown ddc map 0x%02x\n", map[0]);
  246. }
  247. }
  248. /* v2.x: directly write port as dcb i2cidx */
  249. return (port << 4) | port;
  250. }
  251. struct mxms_odev {
  252. u8 outp_type;
  253. u8 conn_type;
  254. u8 ddc_port;
  255. u8 dig_conn;
  256. };
  257. static void
  258. mxms_output_device(struct drm_device *dev, u8 *pdata, struct mxms_odev *desc)
  259. {
  260. u64 data = ROM32(pdata[0]);
  261. if (mxms_version(dev) >= 0x0300)
  262. data |= (u64)ROM16(pdata[4]) << 32;
  263. desc->outp_type = (data & 0x00000000000000f0ULL) >> 4;
  264. desc->ddc_port = (data & 0x0000000000000f00ULL) >> 8;
  265. desc->conn_type = (data & 0x000000000001f000ULL) >> 12;
  266. desc->dig_conn = (data & 0x0000000000780000ULL) >> 19;
  267. }
  268. struct context {
  269. u32 *outp;
  270. struct mxms_odev desc;
  271. };
  272. static bool
  273. mxm_match_tmds_partner(struct drm_device *dev, u8 *data, void *info)
  274. {
  275. struct context *ctx = info;
  276. struct mxms_odev desc;
  277. mxms_output_device(dev, data, &desc);
  278. if (desc.outp_type == 2 &&
  279. desc.dig_conn == ctx->desc.dig_conn)
  280. return false;
  281. return true;
  282. }
  283. static bool
  284. mxm_match_dcb(struct drm_device *dev, u8 *data, void *info)
  285. {
  286. struct context *ctx = info;
  287. u64 desc = *(u64 *)data;
  288. mxms_output_device(dev, data, &ctx->desc);
  289. /* match dcb encoder type to mxm-ods device type */
  290. if ((ctx->outp[0] & 0x0000000f) != ctx->desc.outp_type)
  291. return true;
  292. /* digital output, have some extra stuff to match here, there's a
  293. * table in the vbios that provides a mapping from the mxm digital
  294. * connection enum values to SOR/link
  295. */
  296. if ((desc & 0x00000000000000f0) >= 0x20) {
  297. /* check against sor index */
  298. u8 link = mxm_sor_map(dev, ctx->desc.dig_conn);
  299. if ((ctx->outp[0] & 0x0f000000) != (link & 0x0f) << 24)
  300. return true;
  301. /* check dcb entry has a compatible link field */
  302. link = (link & 0x30) >> 4;
  303. if ((link & ((ctx->outp[1] & 0x00000030) >> 4)) != link)
  304. return true;
  305. }
  306. /* mark this descriptor accounted for by setting invalid device type,
  307. * except of course some manufactures don't follow specs properly and
  308. * we need to avoid killing off the TMDS function on DP connectors
  309. * if MXM-SIS is missing an entry for it.
  310. */
  311. data[0] &= ~0xf0;
  312. if (ctx->desc.outp_type == 6 && ctx->desc.conn_type == 6 &&
  313. mxms_foreach(dev, 0x01, mxm_match_tmds_partner, ctx)) {
  314. data[0] |= 0x20; /* modify descriptor to match TMDS now */
  315. } else {
  316. data[0] |= 0xf0;
  317. }
  318. return false;
  319. }
  320. static int
  321. mxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe)
  322. {
  323. struct context ctx = { .outp = (u32 *)dcbe };
  324. u8 type, i2cidx, link;
  325. u8 *conn;
  326. /* look for an output device structure that matches this dcb entry.
  327. * if one isn't found, disable it.
  328. */
  329. if (mxms_foreach(dev, 0x01, mxm_match_dcb, &ctx)) {
  330. MXM_DBG(dev, "disable %d: 0x%08x 0x%08x\n",
  331. idx, ctx.outp[0], ctx.outp[1]);
  332. ctx.outp[0] |= 0x0000000f;
  333. return 0;
  334. }
  335. /* modify the output's ddc/aux port, there's a pointer to a table
  336. * with the mapping from mxm ddc/aux port to dcb i2c_index in the
  337. * vbios mxm table
  338. */
  339. i2cidx = mxm_ddc_map(dev, ctx.desc.ddc_port);
  340. if ((ctx.outp[0] & 0x0000000f) != OUTPUT_DP)
  341. i2cidx = (i2cidx & 0x0f) << 4;
  342. else
  343. i2cidx = (i2cidx & 0xf0);
  344. if (i2cidx != 0xf0) {
  345. ctx.outp[0] &= ~0x000000f0;
  346. ctx.outp[0] |= i2cidx;
  347. }
  348. /* override dcb sorconf.link, based on what mxm data says */
  349. switch (ctx.desc.outp_type) {
  350. case 0x00: /* Analog CRT */
  351. case 0x01: /* Analog TV/HDTV */
  352. break;
  353. default:
  354. link = mxm_sor_map(dev, ctx.desc.dig_conn) & 0x30;
  355. ctx.outp[1] &= ~0x00000030;
  356. ctx.outp[1] |= link;
  357. break;
  358. }
  359. /* we may need to fixup various other vbios tables based on what
  360. * the descriptor says the connector type should be.
  361. *
  362. * in a lot of cases, the vbios tables will claim DVI-I is possible,
  363. * and the mxm data says the connector is really HDMI. another
  364. * common example is DP->eDP.
  365. */
  366. conn = dcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12);
  367. type = conn[0];
  368. switch (ctx.desc.conn_type) {
  369. case 0x01: /* LVDS */
  370. ctx.outp[1] |= 0x00000004; /* use_power_scripts */
  371. /* XXX: modify default link width in LVDS table */
  372. break;
  373. case 0x02: /* HDMI */
  374. type = DCB_CONNECTOR_HDMI_1;
  375. break;
  376. case 0x03: /* DVI-D */
  377. type = DCB_CONNECTOR_DVI_D;
  378. break;
  379. case 0x0e: /* eDP, falls through to DPint */
  380. ctx.outp[1] |= 0x00010000;
  381. case 0x07: /* DP internal, wtf is this?? HP8670w */
  382. ctx.outp[1] |= 0x00000004; /* use_power_scripts? */
  383. type = DCB_CONNECTOR_eDP;
  384. break;
  385. default:
  386. break;
  387. }
  388. if (mxms_version(dev) >= 0x0300)
  389. conn[0] = type;
  390. return 0;
  391. }
  392. static bool
  393. mxm_show_unmatched(struct drm_device *dev, u8 *data, void *info)
  394. {
  395. u64 desc = *(u64 *)data;
  396. if ((desc & 0xf0) != 0xf0)
  397. MXM_MSG(dev, "unmatched output device 0x%016llx\n", desc);
  398. return true;
  399. }
  400. static void
  401. mxm_dcb_sanitise(struct drm_device *dev)
  402. {
  403. u8 *dcb = dcb_table(dev);
  404. if (!dcb || dcb[0] != 0x40) {
  405. MXM_DBG(dev, "unsupported DCB version\n");
  406. return;
  407. }
  408. dcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry);
  409. mxms_foreach(dev, 0x01, mxm_show_unmatched, NULL);
  410. }
  411. static bool
  412. mxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr,
  413. u8 offset, u8 size, u8 *data)
  414. {
  415. struct i2c_msg msgs[] = {
  416. { .addr = addr, .flags = 0, .len = 1, .buf = &offset },
  417. { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, },
  418. };
  419. return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
  420. }
  421. static bool
  422. mxm_shadow_rom(struct drm_device *dev, u8 version)
  423. {
  424. struct drm_nouveau_private *dev_priv = dev->dev_private;
  425. struct nouveau_i2c_chan *i2c = NULL;
  426. u8 i2cidx, mxms[6], addr, size;
  427. i2cidx = mxm_ddc_map(dev, 1 /* LVDS_DDC */) & 0x0f;
  428. if (i2cidx < 0x0f)
  429. i2c = nouveau_i2c_find(dev, i2cidx);
  430. if (!i2c)
  431. return false;
  432. addr = 0x54;
  433. if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) {
  434. addr = 0x56;
  435. if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms))
  436. return false;
  437. }
  438. dev_priv->mxms = mxms;
  439. size = mxms_headerlen(dev) + mxms_structlen(dev);
  440. dev_priv->mxms = kmalloc(size, GFP_KERNEL);
  441. if (dev_priv->mxms &&
  442. mxm_shadow_rom_fetch(i2c, addr, 0, size, dev_priv->mxms))
  443. return true;
  444. kfree(dev_priv->mxms);
  445. dev_priv->mxms = NULL;
  446. return false;
  447. }
  448. #if defined(CONFIG_ACPI)
  449. static bool
  450. mxm_shadow_dsm(struct drm_device *dev, u8 version)
  451. {
  452. struct drm_nouveau_private *dev_priv = dev->dev_private;
  453. static char muid[] = {
  454. 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C,
  455. 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65
  456. };
  457. u32 mxms_args[] = { 0x00000000 };
  458. union acpi_object args[4] = {
  459. /* _DSM MUID */
  460. { .buffer.type = 3,
  461. .buffer.length = sizeof(muid),
  462. .buffer.pointer = muid,
  463. },
  464. /* spec says this can be zero to mean "highest revision", but
  465. * of course there's at least one bios out there which fails
  466. * unless you pass in exactly the version it supports..
  467. */
  468. { .integer.type = ACPI_TYPE_INTEGER,
  469. .integer.value = (version & 0xf0) << 4 | (version & 0x0f),
  470. },
  471. /* MXMS function */
  472. { .integer.type = ACPI_TYPE_INTEGER,
  473. .integer.value = 0x00000010,
  474. },
  475. /* Pointer to MXMS arguments */
  476. { .buffer.type = ACPI_TYPE_BUFFER,
  477. .buffer.length = sizeof(mxms_args),
  478. .buffer.pointer = (char *)mxms_args,
  479. },
  480. };
  481. struct acpi_object_list list = { ARRAY_SIZE(args), args };
  482. struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };
  483. union acpi_object *obj;
  484. acpi_handle handle;
  485. int ret;
  486. handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
  487. if (!handle)
  488. return false;
  489. ret = acpi_evaluate_object(handle, "_DSM", &list, &retn);
  490. if (ret) {
  491. MXM_DBG(dev, "DSM MXMS failed: %d\n", ret);
  492. return false;
  493. }
  494. obj = retn.pointer;
  495. if (obj->type == ACPI_TYPE_BUFFER) {
  496. dev_priv->mxms = kmemdup(obj->buffer.pointer,
  497. obj->buffer.length, GFP_KERNEL);
  498. } else
  499. if (obj->type == ACPI_TYPE_INTEGER) {
  500. MXM_DBG(dev, "DSM MXMS returned 0x%llx\n", obj->integer.value);
  501. }
  502. kfree(obj);
  503. return dev_priv->mxms != NULL;
  504. }
  505. #endif
  506. #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
  507. #define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
  508. static u8
  509. wmi_wmmx_mxmi(struct drm_device *dev, u8 version)
  510. {
  511. u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 };
  512. struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args };
  513. struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };
  514. union acpi_object *obj;
  515. acpi_status status;
  516. status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn);
  517. if (ACPI_FAILURE(status)) {
  518. MXM_DBG(dev, "WMMX MXMI returned %d\n", status);
  519. return 0x00;
  520. }
  521. obj = retn.pointer;
  522. if (obj->type == ACPI_TYPE_INTEGER) {
  523. version = obj->integer.value;
  524. MXM_DBG(dev, "WMMX MXMI version %d.%d\n",
  525. (version >> 4), version & 0x0f);
  526. } else {
  527. version = 0;
  528. MXM_DBG(dev, "WMMX MXMI returned non-integer\n");
  529. }
  530. kfree(obj);
  531. return version;
  532. }
  533. static bool
  534. mxm_shadow_wmi(struct drm_device *dev, u8 version)
  535. {
  536. struct drm_nouveau_private *dev_priv = dev->dev_private;
  537. u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 };
  538. struct acpi_buffer args = { sizeof(mxms_args), mxms_args };
  539. struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };
  540. union acpi_object *obj;
  541. acpi_status status;
  542. if (!wmi_has_guid(WMI_WMMX_GUID)) {
  543. MXM_DBG(dev, "WMMX GUID not found\n");
  544. return false;
  545. }
  546. mxms_args[1] = wmi_wmmx_mxmi(dev, 0x00);
  547. if (!mxms_args[1])
  548. mxms_args[1] = wmi_wmmx_mxmi(dev, version);
  549. if (!mxms_args[1])
  550. return false;
  551. status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn);
  552. if (ACPI_FAILURE(status)) {
  553. MXM_DBG(dev, "WMMX MXMS returned %d\n", status);
  554. return false;
  555. }
  556. obj = retn.pointer;
  557. if (obj->type == ACPI_TYPE_BUFFER) {
  558. dev_priv->mxms = kmemdup(obj->buffer.pointer,
  559. obj->buffer.length, GFP_KERNEL);
  560. }
  561. kfree(obj);
  562. return dev_priv->mxms != NULL;
  563. }
  564. #endif
  565. struct mxm_shadow_h {
  566. const char *name;
  567. bool (*exec)(struct drm_device *, u8 version);
  568. } _mxm_shadow[] = {
  569. { "ROM", mxm_shadow_rom },
  570. #if defined(CONFIG_ACPI)
  571. { "DSM", mxm_shadow_dsm },
  572. #endif
  573. #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
  574. { "WMI", mxm_shadow_wmi },
  575. #endif
  576. {}
  577. };
  578. static int
  579. mxm_shadow(struct drm_device *dev, u8 version)
  580. {
  581. struct drm_nouveau_private *dev_priv = dev->dev_private;
  582. struct mxm_shadow_h *shadow = _mxm_shadow;
  583. do {
  584. MXM_DBG(dev, "checking %s\n", shadow->name);
  585. if (shadow->exec(dev, version)) {
  586. if (mxms_valid(dev))
  587. return 0;
  588. kfree(dev_priv->mxms);
  589. dev_priv->mxms = NULL;
  590. }
  591. } while ((++shadow)->name);
  592. return -ENOENT;
  593. }
  594. int
  595. nouveau_mxm_init(struct drm_device *dev)
  596. {
  597. u8 mxm_size, *mxm = mxm_table(dev, &mxm_size);
  598. if (!mxm || !mxm[0]) {
  599. MXM_MSG(dev, "no VBIOS data, nothing to do\n");
  600. return 0;
  601. }
  602. MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f);
  603. if (mxm_shadow(dev, mxm[0])) {
  604. MXM_MSG(dev, "failed to locate valid SIS\n");
  605. #if 0
  606. /* we should, perhaps, fall back to some kind of limited
  607. * mode here if the x86 vbios hasn't already done the
  608. * work for us (so we prevent loading with completely
  609. * whacked vbios tables).
  610. */
  611. return -EINVAL;
  612. #else
  613. return 0;
  614. #endif
  615. }
  616. MXM_MSG(dev, "MXMS Version %d.%d\n",
  617. mxms_version(dev) >> 8, mxms_version(dev) & 0xff);
  618. mxms_foreach(dev, 0, NULL, NULL);
  619. if (nouveau_mxmdcb)
  620. mxm_dcb_sanitise(dev);
  621. return 0;
  622. }
  623. void
  624. nouveau_mxm_fini(struct drm_device *dev)
  625. {
  626. struct drm_nouveau_private *dev_priv = dev->dev_private;
  627. kfree(dev_priv->mxms);
  628. dev_priv->mxms = NULL;
  629. }