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
33static u8 *
34mxms_data(struct drm_device *dev)
35{
36	struct drm_nouveau_private *dev_priv = dev->dev_private;
37	return dev_priv->mxms;
38
39}
40
41static u16
42mxms_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
59static u16
60mxms_headerlen(struct drm_device *dev)
61{
62	return 8;
63}
64
65static u16
66mxms_structlen(struct drm_device *dev)
67{
68	return *(u16 *)&mxms_data(dev)[6];
69}
70
71static bool
72mxms_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
85static bool
86mxms_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
100static bool
101mxms_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
185static u8 *
186mxm_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 */
210static 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
215static 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
220static 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
225static 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
230static 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
235static u8
236mxm_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
268static u8
269mxm_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
289struct mxms_odev {
290	u8 outp_type;
291	u8 conn_type;
292	u8 ddc_port;
293	u8 dig_conn;
294};
295
296static void
297mxms_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
309struct context {
310	u32 *outp;
311	struct mxms_odev desc;
312};
313
314static bool
315mxm_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
327static bool
328mxm_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
371static int
372mxm_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
451static bool
452mxm_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
460static void
461mxm_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
473static bool
474mxm_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
485static bool
486mxm_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)
519static bool
520mxm_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
585static u8
586wmi_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
614static bool
615mxm_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
652struct 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
666static int
667mxm_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
683int
684nouveau_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
717void
718nouveau_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