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