1 #include <linux/pci.h> 2 #include <linux/acpi.h> 3 #include <linux/slab.h> 4 #include <acpi/acpi_drivers.h> 5 #include <acpi/acpi_bus.h> 6 #include <acpi/video.h> 7 #include <acpi/acpi.h> 8 #include <linux/mxm-wmi.h> 9 10 #include "drmP.h" 11 #include "drm.h" 12 #include "drm_sarea.h" 13 #include "drm_crtc_helper.h" 14 #include "nouveau_drv.h" 15 #include "nouveau_drm.h" 16 #include "nv50_display.h" 17 #include "nouveau_connector.h" 18 19 #include <linux/vga_switcheroo.h> 20 21 #define NOUVEAU_DSM_SUPPORTED 0x00 22 #define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 23 24 #define NOUVEAU_DSM_ACTIVE 0x01 25 #define NOUVEAU_DSM_ACTIVE_QUERY 0x00 26 27 #define NOUVEAU_DSM_LED 0x02 28 #define NOUVEAU_DSM_LED_STATE 0x00 29 #define NOUVEAU_DSM_LED_OFF 0x10 30 #define NOUVEAU_DSM_LED_STAMINA 0x11 31 #define NOUVEAU_DSM_LED_SPEED 0x12 32 33 #define NOUVEAU_DSM_POWER 0x03 34 #define NOUVEAU_DSM_POWER_STATE 0x00 35 #define NOUVEAU_DSM_POWER_SPEED 0x01 36 #define NOUVEAU_DSM_POWER_STAMINA 0x02 37 38 static struct nouveau_dsm_priv { 39 bool dsm_detected; 40 bool optimus_detected; 41 acpi_handle dhandle; 42 acpi_handle rom_handle; 43 } nouveau_dsm_priv; 44 45 #define NOUVEAU_DSM_HAS_MUX 0x1 46 #define NOUVEAU_DSM_HAS_OPT 0x2 47 48 static const char nouveau_dsm_muid[] = { 49 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D, 50 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, 51 }; 52 53 static const char nouveau_op_dsm_muid[] = { 54 0xF8, 0xD8, 0x86, 0xA4, 0xDA, 0x0B, 0x1B, 0x47, 55 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0, 56 }; 57 58 static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 59 { 60 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 61 struct acpi_object_list input; 62 union acpi_object params[4]; 63 union acpi_object *obj; 64 int err; 65 66 input.count = 4; 67 input.pointer = params; 68 params[0].type = ACPI_TYPE_BUFFER; 69 params[0].buffer.length = sizeof(nouveau_op_dsm_muid); 70 params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; 71 params[1].type = ACPI_TYPE_INTEGER; 72 params[1].integer.value = 0x00000100; 73 params[2].type = ACPI_TYPE_INTEGER; 74 params[2].integer.value = func; 75 params[3].type = ACPI_TYPE_BUFFER; 76 params[3].buffer.length = 0; 77 78 err = acpi_evaluate_object(handle, "_DSM", &input, &output); 79 if (err) { 80 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); 81 return err; 82 } 83 84 obj = (union acpi_object *)output.pointer; 85 86 if (obj->type == ACPI_TYPE_INTEGER) 87 if (obj->integer.value == 0x80000002) { 88 return -ENODEV; 89 } 90 91 if (obj->type == ACPI_TYPE_BUFFER) { 92 if (obj->buffer.length == 4 && result) { 93 *result = 0; 94 *result |= obj->buffer.pointer[0]; 95 *result |= (obj->buffer.pointer[1] << 8); 96 *result |= (obj->buffer.pointer[2] << 16); 97 *result |= (obj->buffer.pointer[3] << 24); 98 } 99 } 100 101 kfree(output.pointer); 102 return 0; 103 } 104 105 static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 106 { 107 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 108 struct acpi_object_list input; 109 union acpi_object params[4]; 110 union acpi_object *obj; 111 int err; 112 113 input.count = 4; 114 input.pointer = params; 115 params[0].type = ACPI_TYPE_BUFFER; 116 params[0].buffer.length = sizeof(nouveau_dsm_muid); 117 params[0].buffer.pointer = (char *)nouveau_dsm_muid; 118 params[1].type = ACPI_TYPE_INTEGER; 119 params[1].integer.value = 0x00000102; 120 params[2].type = ACPI_TYPE_INTEGER; 121 params[2].integer.value = func; 122 params[3].type = ACPI_TYPE_INTEGER; 123 params[3].integer.value = arg; 124 125 err = acpi_evaluate_object(handle, "_DSM", &input, &output); 126 if (err) { 127 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); 128 return err; 129 } 130 131 obj = (union acpi_object *)output.pointer; 132 133 if (obj->type == ACPI_TYPE_INTEGER) 134 if (obj->integer.value == 0x80000002) 135 return -ENODEV; 136 137 if (obj->type == ACPI_TYPE_BUFFER) { 138 if (obj->buffer.length == 4 && result) { 139 *result = 0; 140 *result |= obj->buffer.pointer[0]; 141 *result |= (obj->buffer.pointer[1] << 8); 142 *result |= (obj->buffer.pointer[2] << 16); 143 *result |= (obj->buffer.pointer[3] << 24); 144 } 145 } 146 147 kfree(output.pointer); 148 return 0; 149 } 150 151 static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) 152 { 153 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 154 mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 155 return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); 156 } 157 158 static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) 159 { 160 int arg; 161 if (state == VGA_SWITCHEROO_ON) 162 arg = NOUVEAU_DSM_POWER_SPEED; 163 else 164 arg = NOUVEAU_DSM_POWER_STAMINA; 165 nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); 166 return 0; 167 } 168 169 static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) 170 { 171 if (id == VGA_SWITCHEROO_IGD) 172 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); 173 else 174 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED); 175 } 176 177 static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, 178 enum vga_switcheroo_state state) 179 { 180 if (id == VGA_SWITCHEROO_IGD) 181 return 0; 182 183 return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); 184 } 185 186 static int nouveau_dsm_init(void) 187 { 188 return 0; 189 } 190 191 static int nouveau_dsm_get_client_id(struct pci_dev *pdev) 192 { 193 /* easy option one - intel vendor ID means Integrated */ 194 if (pdev->vendor == PCI_VENDOR_ID_INTEL) 195 return VGA_SWITCHEROO_IGD; 196 197 /* is this device on Bus 0? - this may need improving */ 198 if (pdev->bus->number == 0) 199 return VGA_SWITCHEROO_IGD; 200 201 return VGA_SWITCHEROO_DIS; 202 } 203 204 static struct vga_switcheroo_handler nouveau_dsm_handler = { 205 .switchto = nouveau_dsm_switchto, 206 .power_state = nouveau_dsm_power_state, 207 .init = nouveau_dsm_init, 208 .get_client_id = nouveau_dsm_get_client_id, 209 }; 210 211 static int nouveau_dsm_pci_probe(struct pci_dev *pdev) 212 { 213 acpi_handle dhandle, nvidia_handle; 214 acpi_status status; 215 int ret, retval = 0; 216 uint32_t result; 217 218 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); 219 if (!dhandle) 220 return false; 221 222 status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle); 223 if (ACPI_FAILURE(status)) { 224 return false; 225 } 226 227 ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, 228 NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); 229 if (ret == 0) 230 retval |= NOUVEAU_DSM_HAS_MUX; 231 232 ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); 233 if (ret == 0) 234 retval |= NOUVEAU_DSM_HAS_OPT; 235 236 if (retval) 237 nouveau_dsm_priv.dhandle = dhandle; 238 239 return retval; 240 } 241 242 static bool nouveau_dsm_detect(void) 243 { 244 char acpi_method_name[255] = { 0 }; 245 struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; 246 struct pci_dev *pdev = NULL; 247 int has_dsm = 0; 248 int has_optimus; 249 int vga_count = 0; 250 bool guid_valid; 251 int retval; 252 bool ret = false; 253 254 /* lookup the MXM GUID */ 255 guid_valid = mxm_wmi_supported(); 256 257 if (guid_valid) 258 printk("MXM: GUID detected in BIOS\n"); 259 260 /* now do DSM detection */ 261 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 262 vga_count++; 263 264 retval = nouveau_dsm_pci_probe(pdev); 265 if (retval & NOUVEAU_DSM_HAS_MUX) 266 has_dsm |= 1; 267 if (retval & NOUVEAU_DSM_HAS_OPT) 268 has_optimus = 1; 269 } 270 271 if (vga_count == 2 && has_dsm && guid_valid) { 272 acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); 273 printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", 274 acpi_method_name); 275 nouveau_dsm_priv.dsm_detected = true; 276 ret = true; 277 } 278 279 if (has_optimus == 1) 280 nouveau_dsm_priv.optimus_detected = true; 281 282 return ret; 283 } 284 285 void nouveau_register_dsm_handler(void) 286 { 287 bool r; 288 289 r = nouveau_dsm_detect(); 290 if (!r) 291 return; 292 293 vga_switcheroo_register_handler(&nouveau_dsm_handler); 294 } 295 296 void nouveau_unregister_dsm_handler(void) 297 { 298 vga_switcheroo_unregister_handler(); 299 } 300 301 /* retrieve the ROM in 4k blocks */ 302 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios, 303 int offset, int len) 304 { 305 acpi_status status; 306 union acpi_object rom_arg_elements[2], *obj; 307 struct acpi_object_list rom_arg; 308 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 309 310 rom_arg.count = 2; 311 rom_arg.pointer = &rom_arg_elements[0]; 312 313 rom_arg_elements[0].type = ACPI_TYPE_INTEGER; 314 rom_arg_elements[0].integer.value = offset; 315 316 rom_arg_elements[1].type = ACPI_TYPE_INTEGER; 317 rom_arg_elements[1].integer.value = len; 318 319 status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer); 320 if (ACPI_FAILURE(status)) { 321 printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status)); 322 return -ENODEV; 323 } 324 obj = (union acpi_object *)buffer.pointer; 325 memcpy(bios+offset, obj->buffer.pointer, len); 326 kfree(buffer.pointer); 327 return len; 328 } 329 330 bool nouveau_acpi_rom_supported(struct pci_dev *pdev) 331 { 332 acpi_status status; 333 acpi_handle dhandle, rom_handle; 334 335 if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected) 336 return false; 337 338 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); 339 if (!dhandle) 340 return false; 341 342 status = acpi_get_handle(dhandle, "_ROM", &rom_handle); 343 if (ACPI_FAILURE(status)) 344 return false; 345 346 nouveau_dsm_priv.rom_handle = rom_handle; 347 return true; 348 } 349 350 int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) 351 { 352 return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); 353 } 354 355 int 356 nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) 357 { 358 struct nouveau_connector *nv_connector = nouveau_connector(connector); 359 struct acpi_device *acpidev; 360 acpi_handle handle; 361 int type, ret; 362 void *edid; 363 364 switch (connector->connector_type) { 365 case DRM_MODE_CONNECTOR_LVDS: 366 case DRM_MODE_CONNECTOR_eDP: 367 type = ACPI_VIDEO_DISPLAY_LCD; 368 break; 369 default: 370 return -EINVAL; 371 } 372 373 handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); 374 if (!handle) 375 return -ENODEV; 376 377 ret = acpi_bus_get_device(handle, &acpidev); 378 if (ret) 379 return -ENODEV; 380 381 ret = acpi_video_get_edid(acpidev, type, -1, &edid); 382 if (ret < 0) 383 return ret; 384 385 nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); 386 return 0; 387 } 388