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>
10
#include "drm_sarea.h"
11
#include "drm_crtc_helper.h"
12
#include "nouveau_drv.h"
13
#include "nouveau_drm.h"
14
#include "nv50_display.h"
15
#include "nouveau_connector.h"
17
#include <linux/vga_switcheroo.h>
19
#define NOUVEAU_DSM_SUPPORTED 0x00
20
#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00
22
#define NOUVEAU_DSM_ACTIVE 0x01
23
#define NOUVEAU_DSM_ACTIVE_QUERY 0x00
25
#define NOUVEAU_DSM_LED 0x02
26
#define NOUVEAU_DSM_LED_STATE 0x00
27
#define NOUVEAU_DSM_LED_OFF 0x10
28
#define NOUVEAU_DSM_LED_STAMINA 0x11
29
#define NOUVEAU_DSM_LED_SPEED 0x12
31
#define NOUVEAU_DSM_POWER 0x03
32
#define NOUVEAU_DSM_POWER_STATE 0x00
33
#define NOUVEAU_DSM_POWER_SPEED 0x01
34
#define NOUVEAU_DSM_POWER_STAMINA 0x02
36
static struct nouveau_dsm_priv {
39
acpi_handle rom_handle;
42
static const char nouveau_dsm_muid[] = {
43
0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
44
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
47
static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
49
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
50
struct acpi_object_list input;
51
union acpi_object params[4];
52
union acpi_object *obj;
56
input.pointer = params;
57
params[0].type = ACPI_TYPE_BUFFER;
58
params[0].buffer.length = sizeof(nouveau_dsm_muid);
59
params[0].buffer.pointer = (char *)nouveau_dsm_muid;
60
params[1].type = ACPI_TYPE_INTEGER;
61
params[1].integer.value = 0x00000102;
62
params[2].type = ACPI_TYPE_INTEGER;
63
params[2].integer.value = func;
64
params[3].type = ACPI_TYPE_INTEGER;
65
params[3].integer.value = arg;
67
err = acpi_evaluate_object(handle, "_DSM", &input, &output);
69
printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
73
obj = (union acpi_object *)output.pointer;
75
if (obj->type == ACPI_TYPE_INTEGER)
76
if (obj->integer.value == 0x80000002)
79
if (obj->type == ACPI_TYPE_BUFFER) {
80
if (obj->buffer.length == 4 && result) {
82
*result |= obj->buffer.pointer[0];
83
*result |= (obj->buffer.pointer[1] << 8);
84
*result |= (obj->buffer.pointer[2] << 16);
85
*result |= (obj->buffer.pointer[3] << 24);
89
kfree(output.pointer);
93
static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
95
return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL);
98
static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
101
if (state == VGA_SWITCHEROO_ON)
102
arg = NOUVEAU_DSM_POWER_SPEED;
104
arg = NOUVEAU_DSM_POWER_STAMINA;
105
nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL);
109
static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
111
if (id == VGA_SWITCHEROO_IGD)
112
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
114
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
117
static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
118
enum vga_switcheroo_state state)
120
if (id == VGA_SWITCHEROO_IGD)
123
return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
126
static int nouveau_dsm_init(void)
131
static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
133
/* easy option one - intel vendor ID means Integrated */
134
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
135
return VGA_SWITCHEROO_IGD;
137
/* is this device on Bus 0? - this may need improving */
138
if (pdev->bus->number == 0)
139
return VGA_SWITCHEROO_IGD;
141
return VGA_SWITCHEROO_DIS;
144
static struct vga_switcheroo_handler nouveau_dsm_handler = {
145
.switchto = nouveau_dsm_switchto,
146
.power_state = nouveau_dsm_power_state,
147
.init = nouveau_dsm_init,
148
.get_client_id = nouveau_dsm_get_client_id,
151
static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
153
acpi_handle dhandle, nvidia_handle;
158
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
162
status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
163
if (ACPI_FAILURE(status)) {
167
ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
168
NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
172
nouveau_dsm_priv.dhandle = dhandle;
176
static bool nouveau_dsm_detect(void)
178
char acpi_method_name[255] = { 0 };
179
struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
180
struct pci_dev *pdev = NULL;
184
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
187
has_dsm |= (nouveau_dsm_pci_probe(pdev) == true);
190
if (vga_count == 2 && has_dsm) {
191
acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
192
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
194
nouveau_dsm_priv.dsm_detected = true;
200
void nouveau_register_dsm_handler(void)
204
r = nouveau_dsm_detect();
208
vga_switcheroo_register_handler(&nouveau_dsm_handler);
211
void nouveau_unregister_dsm_handler(void)
213
vga_switcheroo_unregister_handler();
216
/* retrieve the ROM in 4k blocks */
217
static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
221
union acpi_object rom_arg_elements[2], *obj;
222
struct acpi_object_list rom_arg;
223
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
226
rom_arg.pointer = &rom_arg_elements[0];
228
rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
229
rom_arg_elements[0].integer.value = offset;
231
rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
232
rom_arg_elements[1].integer.value = len;
234
status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
235
if (ACPI_FAILURE(status)) {
236
printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
239
obj = (union acpi_object *)buffer.pointer;
240
memcpy(bios+offset, obj->buffer.pointer, len);
241
kfree(buffer.pointer);
245
bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
248
acpi_handle dhandle, rom_handle;
250
if (!nouveau_dsm_priv.dsm_detected)
253
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
257
status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
258
if (ACPI_FAILURE(status))
261
nouveau_dsm_priv.rom_handle = rom_handle;
265
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
267
return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
271
nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
273
struct nouveau_connector *nv_connector = nouveau_connector(connector);
274
struct acpi_device *acpidev;
279
switch (connector->connector_type) {
280
case DRM_MODE_CONNECTOR_LVDS:
281
case DRM_MODE_CONNECTOR_eDP:
282
type = ACPI_VIDEO_DISPLAY_LCD;
288
handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
292
ret = acpi_bus_get_device(handle, &acpidev);
296
ret = acpi_video_get_edid(acpidev, type, -1, &edid);
300
nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL);