1b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs/* 2b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * Copyright 2011 Red Hat Inc. 3b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 4b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * copy of this software and associated documentation files (the "Software"), 6b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * to deal in the Software without restriction, including without limitation 7b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * Software is furnished to do so, subject to the following conditions: 10b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 11b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * The above copyright notice and this permission notice shall be included in 12b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * all copies or substantial portions of the Software. 13b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 14b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 22b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * Authors: Ben Skeggs 23b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 24b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 2593d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#include <linux/acpi.h> 2693d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 27b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs#include "drmP.h" 28b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs#include "nouveau_drv.h" 29b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 30b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs#define MXM_DBG(dev, fmt, args...) NV_DEBUG((dev), "MXM: " fmt, ##args) 31b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs#define MXM_MSG(dev, fmt, args...) NV_INFO((dev), "MXM: " fmt, ##args) 32b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 33b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 * 34b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_data(struct drm_device *dev) 35b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 36b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 37b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return dev_priv->mxms; 38b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 39b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 40b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 41b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u16 42b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_version(struct drm_device *dev) 43b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 44b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *mxms = mxms_data(dev); 45b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u16 version = (mxms[4] << 8) | mxms[5]; 46b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs switch (version ) { 47b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x0200: 48b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x0201: 49b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x0300: 50b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return version; 51b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs default: 52b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 53b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 54b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 55b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "unknown version %d.%d\n", mxms[4], mxms[5]); 56b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0x0000; 57b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 58b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 59b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u16 60b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_headerlen(struct drm_device *dev) 61b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 62b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 8; 63b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 64b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 65b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u16 66b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_structlen(struct drm_device *dev) 67b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 68b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return *(u16 *)&mxms_data(dev)[6]; 69b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 70b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 71b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 72b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_checksum(struct drm_device *dev) 73b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 74b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u16 size = mxms_headerlen(dev) + mxms_structlen(dev); 75b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *mxms = mxms_data(dev), sum = 0; 76b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs while (size--) 77b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs sum += *mxms++; 78b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (sum) { 79b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "checksum invalid\n"); 80b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 81b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 82b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 83b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 84b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 85b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 86b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_valid(struct drm_device *dev) 87b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 88b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *mxms = mxms_data(dev); 89b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (*(u32 *)mxms != 0x5f4d584d) { 90b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "signature invalid\n"); 91b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 92b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 93b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 94b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (!mxms_version(dev) || !mxms_checksum(dev)) 95b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 96b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 97b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 98b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 99b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 100b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 101b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_foreach(struct drm_device *dev, u8 types, 102b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs bool (*exec)(struct drm_device *, u8 *, void *), void *info) 103b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 104b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *mxms = mxms_data(dev); 105b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *desc = mxms + mxms_headerlen(dev); 106b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *fini = desc + mxms_structlen(dev) - 1; 107b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs while (desc < fini) { 108b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 type = desc[0] & 0x0f; 109b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 headerlen = 0; 110b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 recordlen = 0; 111b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 entries = 0; 112b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 113b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs switch (type) { 114b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0: /* Output Device Structure */ 115b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_version(dev) >= 0x0300) 116b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 8; 117b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs else 118b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 6; 119b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 120b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 1: /* System Cooling Capability Structure */ 121b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 2: /* Thermal Structure */ 122b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 3: /* Input Power Structure */ 123b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 4; 124b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 125b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 4: /* GPIO Device Structure */ 126b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 4; 127b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs recordlen = 2; 128b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs entries = (ROM32(desc[0]) & 0x01f00000) >> 20; 129b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 130b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 5: /* Vendor Specific Structure */ 131b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 8; 132b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 133b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 6: /* Backlight Control Structure */ 134b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_version(dev) >= 0x0300) { 135b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 4; 136b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs recordlen = 8; 137b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs entries = (desc[1] & 0xf0) >> 4; 138b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } else { 139b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 8; 140b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 141b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 142b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 7: /* Fan Control Structure */ 143b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs headerlen = 8; 144b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs recordlen = 4; 145b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs entries = desc[1] & 0x07; 146b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 147b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs default: 148b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "unknown descriptor type %d\n", type); 149b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 150b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 151b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 152b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((drm_debug & DRM_UT_DRIVER) && (exec == NULL)) { 153b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs static const char * mxms_desc_name[] = { 154b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs "ODS", "SCCS", "TS", "IPS", 155b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs "GSD", "VSS", "BCS", "FCS", 156b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs }; 157b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *dump = desc; 158b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs int i, j; 159b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 160b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "%4s: ", mxms_desc_name[type]); 161b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs for (j = headerlen - 1; j >= 0; j--) 162b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs printk("%02x", dump[j]); 163b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs printk("\n"); 164b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs dump += headerlen; 165b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 166b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs for (i = 0; i < entries; i++, dump += recordlen) { 167b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, " "); 168b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs for (j = recordlen - 1; j >= 0; j--) 169b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs printk("%02x", dump[j]); 170b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs printk("\n"); 171b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 172b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 173b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 174b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (types & (1 << type)) { 175b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (!exec(dev, desc, info)) 176b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 177b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 178b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 179b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc += headerlen + (entries * recordlen); 180b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 181b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 182b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 183b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 184b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 185b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 * 186b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_table(struct drm_device *dev, u8 *size) 187b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 188b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct bit_entry x; 189b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 190b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (bit_table(dev, 'x', &x)) { 191b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "BIT 'x' table not present\n"); 192b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return NULL; 193b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 194b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 195b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (x.version != 1 || x.length < 3) { 196b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "BIT x table %d/%d unknown\n", 197b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs x.version, x.length); 198b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return NULL; 199b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 200b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 201b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs *size = x.length; 202b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return x.data; 203b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 204b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 205b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs/* These map MXM v2.x digital connection values to the appropriate SOR/link, 206b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * hopefully they're correct for all boards within the same chipset... 207b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 208b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * MXM v3.x VBIOS are nicer and provide pointers to these tables. 209b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 210b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 nv84_sor_map[16] = { 211b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, 212b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 213b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 214b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 215b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 nv92_sor_map[16] = { 216b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, 217b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 218b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 219b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 220b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 nv94_sor_map[16] = { 221b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x14, 0x24, 0x11, 0x34, 0x31, 0x11, 0x31, 222b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 223b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 224b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 225b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 nv96_sor_map[16] = { 226b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x14, 0x24, 0x00, 0x34, 0x00, 0x11, 0x31, 227b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 228b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 229b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 230b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 nv98_sor_map[16] = { 231b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x00, 0x14, 0x12, 0x11, 0x00, 0x31, 0x11, 0x31, 232b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 233b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 234b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 235b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 236b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_sor_map(struct drm_device *dev, u8 conn) 237b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 238b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 239b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 len, *mxm = mxm_table(dev, &len); 240b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxm && len >= 6) { 241b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *map = ROMPTR(dev, mxm[4]); 242b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (map) { 243b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (map[0] == 0x10) { 244b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (conn < map[3]) 245b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return map[map[1] + conn]; 246b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0x00; 247b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 248b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 249b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "unknown sor map 0x%02x\n", map[0]); 250b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 251b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 252b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 253b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (dev_priv->chipset == 0x84 || dev_priv->chipset == 0x86) 254b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return nv84_sor_map[conn]; 255b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (dev_priv->chipset == 0x92) 256b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return nv92_sor_map[conn]; 257b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (dev_priv->chipset == 0x94) 258b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return nv94_sor_map[conn]; 259b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (dev_priv->chipset == 0x96) 260b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return nv96_sor_map[conn]; 261b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (dev_priv->chipset == 0x98) 262b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return nv98_sor_map[conn]; 263b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 264b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "missing sor map\n"); 265b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0x00; 266b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 267b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 268b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic u8 269b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_ddc_map(struct drm_device *dev, u8 port) 270b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 271b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 len, *mxm = mxm_table(dev, &len); 272b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxm && len >= 8) { 273b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *map = ROMPTR(dev, mxm[6]); 274b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (map) { 275b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (map[0] == 0x10) { 276b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (port < map[3]) 277b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return map[map[1] + port]; 278b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0x00; 279b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 280b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 281b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "unknown ddc map 0x%02x\n", map[0]); 282b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 283b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 284b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 285b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* v2.x: directly write port as dcb i2cidx */ 286b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return (port << 4) | port; 287b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 288b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 289b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstruct mxms_odev { 290b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 outp_type; 291b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 conn_type; 292b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 ddc_port; 293b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 dig_conn; 294b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 295b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 296b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic void 297b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxms_output_device(struct drm_device *dev, u8 *pdata, struct mxms_odev *desc) 298b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 299b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u64 data = ROM32(pdata[0]); 300b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_version(dev) >= 0x0300) 301b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs data |= (u64)ROM16(pdata[4]) << 32; 302b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 303b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc->outp_type = (data & 0x00000000000000f0ULL) >> 4; 304b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc->ddc_port = (data & 0x0000000000000f00ULL) >> 8; 305b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc->conn_type = (data & 0x000000000001f000ULL) >> 12; 306b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc->dig_conn = (data & 0x0000000000780000ULL) >> 19; 307b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 308b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 309b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstruct context { 310b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u32 *outp; 311b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct mxms_odev desc; 312b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 313b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 314b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 315b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_match_tmds_partner(struct drm_device *dev, u8 *data, void *info) 316b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 317b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct context *ctx = info; 318b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct mxms_odev desc; 319b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 320b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_output_device(dev, data, &desc); 321b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (desc.outp_type == 2 && 322b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs desc.dig_conn == ctx->desc.dig_conn) 323b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 324b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 325b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 326b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 327b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 328b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_match_dcb(struct drm_device *dev, u8 *data, void *info) 329b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 330b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct context *ctx = info; 331b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u64 desc = *(u64 *)data; 332b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 333b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_output_device(dev, data, &ctx->desc); 334b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 335b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* match dcb encoder type to mxm-ods device type */ 336b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((ctx->outp[0] & 0x0000000f) != ctx->desc.outp_type) 337b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 338b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 339b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* digital output, have some extra stuff to match here, there's a 340b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * table in the vbios that provides a mapping from the mxm digital 341b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * connection enum values to SOR/link 342b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 343b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((desc & 0x00000000000000f0) >= 0x20) { 344b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* check against sor index */ 345b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 link = mxm_sor_map(dev, ctx->desc.dig_conn); 346b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((ctx->outp[0] & 0x0f000000) != (link & 0x0f) << 24) 347b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 348b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 349b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* check dcb entry has a compatible link field */ 350b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs link = (link & 0x30) >> 4; 351b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((link & ((ctx->outp[1] & 0x00000030) >> 4)) != link) 352b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 353b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 354b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 355b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* mark this descriptor accounted for by setting invalid device type, 356b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * except of course some manufactures don't follow specs properly and 357b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * we need to avoid killing off the TMDS function on DP connectors 358b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * if MXM-SIS is missing an entry for it. 359b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 360b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs data[0] &= ~0xf0; 361b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (ctx->desc.outp_type == 6 && ctx->desc.conn_type == 6 && 362b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_foreach(dev, 0x01, mxm_match_tmds_partner, ctx)) { 363b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs data[0] |= 0x20; /* modify descriptor to match TMDS now */ 364b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } else { 365b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs data[0] |= 0xf0; 366b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 367b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 368b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 369b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 370b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 371b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic int 372b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe) 373b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 374b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct context ctx = { .outp = (u32 *)dcbe }; 375b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 type, i2cidx, link; 376b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *conn; 377b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 378b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* look for an output device structure that matches this dcb entry. 379b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * if one isn't found, disable it. 380b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 381b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_foreach(dev, 0x01, mxm_match_dcb, &ctx)) { 382b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "disable %d: 0x%08x 0x%08x\n", 383b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs idx, ctx.outp[0], ctx.outp[1]); 384b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[0] |= 0x0000000f; 385b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0; 386b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 387b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 388b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* modify the output's ddc/aux port, there's a pointer to a table 389b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * with the mapping from mxm ddc/aux port to dcb i2c_index in the 390b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * vbios mxm table 391b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 392b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs i2cidx = mxm_ddc_map(dev, ctx.desc.ddc_port); 393b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((ctx.outp[0] & 0x0000000f) != OUTPUT_DP) 394b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs i2cidx = (i2cidx & 0x0f) << 4; 395b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs else 396b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs i2cidx = (i2cidx & 0xf0); 397b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 398b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (i2cidx != 0xf0) { 399b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[0] &= ~0x000000f0; 400b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[0] |= i2cidx; 401b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 402b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 403b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* override dcb sorconf.link, based on what mxm data says */ 404b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs switch (ctx.desc.outp_type) { 405b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x00: /* Analog CRT */ 406b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x01: /* Analog TV/HDTV */ 407b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 408b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs default: 409b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs link = mxm_sor_map(dev, ctx.desc.dig_conn) & 0x30; 410b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[1] &= ~0x00000030; 411b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[1] |= link; 412b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 413b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 414b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 415b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* we may need to fixup various other vbios tables based on what 416b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * the descriptor says the connector type should be. 417b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * 418b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * in a lot of cases, the vbios tables will claim DVI-I is possible, 419b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * and the mxm data says the connector is really HDMI. another 420b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs * common example is DP->eDP. 421b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs */ 422b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs conn = dcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12); 423b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs type = conn[0]; 424b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs switch (ctx.desc.conn_type) { 425b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x01: /* LVDS */ 426b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[1] |= 0x00000004; /* use_power_scripts */ 427b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs /* XXX: modify default link width in LVDS table */ 428b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 429b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x02: /* HDMI */ 430b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs type = DCB_CONNECTOR_HDMI_1; 431b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 432b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x03: /* DVI-D */ 433b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs type = DCB_CONNECTOR_DVI_D; 434b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 435b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x0e: /* eDP, falls through to DPint */ 436b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[1] |= 0x00010000; 437b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs case 0x07: /* DP internal, wtf is this?? HP8670w */ 438b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs ctx.outp[1] |= 0x00000004; /* use_power_scripts? */ 439b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs type = DCB_CONNECTOR_eDP; 440b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 441b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs default: 442b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs break; 443b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 444b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 445b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_version(dev) >= 0x0300) 446b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs conn[0] = type; 447b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 448b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0; 449b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 450b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 451b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 452b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_show_unmatched(struct drm_device *dev, u8 *data, void *info) 453b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 454b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u64 desc = *(u64 *)data; 455b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if ((desc & 0xf0) != 0xf0) 456b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "unmatched output device 0x%016llx\n", desc); 457b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return true; 458b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 459b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 460b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic void 461b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsmxm_dcb_sanitise(struct drm_device *dev) 462b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 463b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 *dcb = dcb_table(dev); 464b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (!dcb || dcb[0] != 0x40) { 465b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "unsupported DCB version\n"); 466b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return; 467b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 468b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 469b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs dcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry); 470b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_foreach(dev, 0x01, mxm_show_unmatched, NULL); 471b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 472b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 473b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 474c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggsmxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr, 475c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs u8 offset, u8 size, u8 *data) 476c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs{ 477c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs struct i2c_msg msgs[] = { 478c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs { .addr = addr, .flags = 0, .len = 1, .buf = &offset }, 479c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, 480c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs }; 481c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 482c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs return i2c_transfer(&i2c->adapter, msgs, 2) == 2; 483c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs} 484c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 485c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggsstatic bool 48693d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggsmxm_shadow_rom(struct drm_device *dev, u8 version) 487b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 488c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 489c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs struct nouveau_i2c_chan *i2c = NULL; 490c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs u8 i2cidx, mxms[6], addr, size; 491c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 492c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs i2cidx = mxm_ddc_map(dev, 1 /* LVDS_DDC */) & 0x0f; 493c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs if (i2cidx < 0x0f) 494c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs i2c = nouveau_i2c_find(dev, i2cidx); 495c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs if (!i2c) 496c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs return false; 497c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 498c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs addr = 0x54; 499c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) { 500c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs addr = 0x56; 501c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) 502c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs return false; 503c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs } 504c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 505c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs dev_priv->mxms = mxms; 506c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs size = mxms_headerlen(dev) + mxms_structlen(dev); 507c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs dev_priv->mxms = kmalloc(size, GFP_KERNEL); 508c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 509c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs if (dev_priv->mxms && 510c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs mxm_shadow_rom_fetch(i2c, addr, 0, size, dev_priv->mxms)) 511c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs return true; 512c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs 513c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs kfree(dev_priv->mxms); 514c37e99050c84c40441e614bd41474e12b6cc2079Ben Skeggs dev_priv->mxms = NULL; 515b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return false; 516b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 517b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 5183952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs#if defined(CONFIG_ACPI) 519b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic bool 52093d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggsmxm_shadow_dsm(struct drm_device *dev, u8 version) 521b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 5223952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 5233952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs static char muid[] = { 5243952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, 5253952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 5263952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }; 5273952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs u32 mxms_args[] = { 0x00000000 }; 5283952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs union acpi_object args[4] = { 5293952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs /* _DSM MUID */ 5303952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs { .buffer.type = 3, 5313952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .buffer.length = sizeof(muid), 5323952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .buffer.pointer = muid, 5333952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }, 5343952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs /* spec says this can be zero to mean "highest revision", but 5353952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs * of course there's at least one bios out there which fails 5363952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs * unless you pass in exactly the version it supports.. 5373952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs */ 5383952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs { .integer.type = ACPI_TYPE_INTEGER, 5393952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .integer.value = (version & 0xf0) << 4 | (version & 0x0f), 5403952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }, 5413952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs /* MXMS function */ 5423952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs { .integer.type = ACPI_TYPE_INTEGER, 5433952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .integer.value = 0x00000010, 5443952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }, 5453952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs /* Pointer to MXMS arguments */ 5463952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs { .buffer.type = ACPI_TYPE_BUFFER, 5473952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .buffer.length = sizeof(mxms_args), 5483952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs .buffer.pointer = (char *)mxms_args, 5493952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }, 5503952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs }; 5513952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs struct acpi_object_list list = { ARRAY_SIZE(args), args }; 5523952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; 5533952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs union acpi_object *obj; 5543952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs acpi_handle handle; 5553952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs int ret; 5563952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 5573952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); 5583952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs if (!handle) 5593952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs return false; 5603952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 5613952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); 5623952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs if (ret) { 5633952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs MXM_DBG(dev, "DSM MXMS failed: %d\n", ret); 5643952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs return false; 5653952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs } 5663952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 5673952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs obj = retn.pointer; 5683952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs if (obj->type == ACPI_TYPE_BUFFER) { 5693952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs dev_priv->mxms = kmemdup(obj->buffer.pointer, 5703952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs obj->buffer.length, GFP_KERNEL); 5713952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs } else 5723952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs if (obj->type == ACPI_TYPE_INTEGER) { 5733952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs MXM_DBG(dev, "DSM MXMS returned 0x%llx\n", obj->integer.value); 5743952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs } 5753952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs 5763952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs kfree(obj); 5773952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs return dev_priv->mxms != NULL; 578b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 5793952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs#endif 580b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 58193d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) 58293d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 58393d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" 58493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 58584ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggsstatic u8 58684ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggswmi_wmmx_mxmi(struct drm_device *dev, u8 version) 58784ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs{ 58884ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 }; 58984ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args }; 59084ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; 59184ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs union acpi_object *obj; 59284ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs acpi_status status; 59384ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs 59484ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); 59584ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs if (ACPI_FAILURE(status)) { 59684ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs MXM_DBG(dev, "WMMX MXMI returned %d\n", status); 59784ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs return 0x00; 59884ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs } 59984ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs 60084ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs obj = retn.pointer; 60184ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs if (obj->type == ACPI_TYPE_INTEGER) { 60284ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs version = obj->integer.value; 60384ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs MXM_DBG(dev, "WMMX MXMI version %d.%d\n", 60484ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs (version >> 4), version & 0x0f); 60584ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs } else { 60684ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs version = 0; 60784ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs MXM_DBG(dev, "WMMX MXMI returned non-integer\n"); 60884ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs } 60984ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs 61084ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs kfree(obj); 61184ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs return version; 61284ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs} 61384ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs 61493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggsstatic bool 61593d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggsmxm_shadow_wmi(struct drm_device *dev, u8 version) 61693d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs{ 61793d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 61893d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; 61993d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; 62093d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; 62193d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs union acpi_object *obj; 62293d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs acpi_status status; 62393d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 62484ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs if (!wmi_has_guid(WMI_WMMX_GUID)) { 62584ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs MXM_DBG(dev, "WMMX GUID not found\n"); 62684ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs return false; 62784ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs } 62884ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs 62984ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs mxms_args[1] = wmi_wmmx_mxmi(dev, 0x00); 63084ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs if (!mxms_args[1]) 63184ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs mxms_args[1] = wmi_wmmx_mxmi(dev, version); 63284ddfda6d4765e410981edeef81c9b5a5a1ce87bBen Skeggs if (!mxms_args[1]) 63393d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs return false; 63493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 63593d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); 63693d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs if (ACPI_FAILURE(status)) { 63793d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs MXM_DBG(dev, "WMMX MXMS returned %d\n", status); 63893d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs return false; 63993d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs } 64093d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 64193d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs obj = retn.pointer; 64293d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs if (obj->type == ACPI_TYPE_BUFFER) { 64393d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs dev_priv->mxms = kmemdup(obj->buffer.pointer, 64493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs obj->buffer.length, GFP_KERNEL); 64593d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs } 64693d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 64793d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs kfree(obj); 64893d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs return dev_priv->mxms != NULL; 64993d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs} 65093d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#endif 65193d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs 652b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstruct mxm_shadow_h { 653b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs const char *name; 65493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs bool (*exec)(struct drm_device *, u8 version); 655b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} _mxm_shadow[] = { 656b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs { "ROM", mxm_shadow_rom }, 6573952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs#if defined(CONFIG_ACPI) 658b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs { "DSM", mxm_shadow_dsm }, 6593952315b9d20fb04d43d184f9c1475327811c5aaBen Skeggs#endif 66093d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) 66193d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs { "WMI", mxm_shadow_wmi }, 66293d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs#endif 663b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs {} 664b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs}; 665b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 666b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsstatic int 66793d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggsmxm_shadow(struct drm_device *dev, u8 version) 668b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 669b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 670b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct mxm_shadow_h *shadow = _mxm_shadow; 671b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs do { 672b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_DBG(dev, "checking %s\n", shadow->name); 67393d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs if (shadow->exec(dev, version)) { 674b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (mxms_valid(dev)) 675b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0; 676b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs kfree(dev_priv->mxms); 677b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs dev_priv->mxms = NULL; 678b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 679b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } while ((++shadow)->name); 680b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return -ENOENT; 681b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 682b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 683b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsint 684b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsnouveau_mxm_init(struct drm_device *dev) 685b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 686b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs u8 mxm_size, *mxm = mxm_table(dev, &mxm_size); 687b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (!mxm || !mxm[0]) { 688b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "no VBIOS data, nothing to do\n"); 689b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0; 690b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 691b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 692b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f); 693b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 69493d9206d08dd18e3aaeed90a3e076b8c323fdd72Ben Skeggs if (mxm_shadow(dev, mxm[0])) { 695b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "failed to locate valid SIS\n"); 696ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs#if 0 697ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs /* we should, perhaps, fall back to some kind of limited 698ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs * mode here if the x86 vbios hasn't already done the 699ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs * work for us (so we prevent loading with completely 700ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs * whacked vbios tables). 701ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs */ 702b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return -EINVAL; 703ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs#else 704ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs return 0; 705ce2e7895faba8fabaa917f52293126e5f4174fa9Ben Skeggs#endif 706b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs } 707b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 708b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs MXM_MSG(dev, "MXMS Version %d.%d\n", 709b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_version(dev) >> 8, mxms_version(dev) & 0xff); 710b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxms_foreach(dev, 0, NULL, NULL); 711b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 712b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs if (nouveau_mxmdcb) 713b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs mxm_dcb_sanitise(dev); 714b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs return 0; 715b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 716b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs 717b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsvoid 718b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggsnouveau_mxm_fini(struct drm_device *dev) 719b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs{ 720b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 721b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs kfree(dev_priv->mxms); 722b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs dev_priv->mxms = NULL; 723b4c26818aeb4159dd537eff6453ae5ebf7a69723Ben Skeggs} 724