Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -urNp linux-2.6.37//drivers/gpu/drm/drm_fops.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/drm_fops.c
- --- linux-2.6.37//drivers/gpu/drm/drm_fops.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/drm_fops.c 2011-01-15 15:12:12.000000000 -0200
- @@ -236,6 +236,8 @@ static int drm_open_helper(struct inode
- return -EBUSY; /* No exclusive opens */
- if (!drm_cpu_valid())
- return -EINVAL;
- + if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
- + return -EINVAL;
- DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
- diff -urNp linux-2.6.37//drivers/gpu/drm/i915/i915_dma.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/i915_dma.c
- --- linux-2.6.37//drivers/gpu/drm/i915/i915_dma.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/i915_dma.c 2011-01-15 15:13:34.000000000 -0200
- @@ -1176,12 +1176,16 @@ static void i915_switcheroo_set_state(st
- pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
- if (state == VGA_SWITCHEROO_ON) {
- printk(KERN_INFO "i915: switched on\n");
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- /* i915 resume handler doesn't set to D0 */
- pci_set_power_state(dev->pdev, PCI_D0);
- i915_resume(dev);
- + dev->switch_power_state = DRM_SWITCH_POWER_ON;
- } else {
- printk(KERN_ERR "i915: switched off\n");
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- i915_suspend(dev, pmm);
- + dev->switch_power_state = DRM_SWITCH_POWER_OFF;
- }
- }
- @@ -1252,6 +1256,7 @@ static int i915_load_modeset_init(struct
- ret = vga_switcheroo_register_client(dev->pdev,
- i915_switcheroo_set_state,
- + NULL,
- i915_switcheroo_can_switch);
- if (ret)
- goto cleanup_vga_client;
- diff -urNp linux-2.6.37//drivers/gpu/drm/i915/i915_drv.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/i915_drv.c
- --- linux-2.6.37//drivers/gpu/drm/i915/i915_drv.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/i915_drv.c 2011-01-15 15:16:23.000000000 -0200
- @@ -248,6 +248,8 @@ static int i915_drm_freeze(struct drm_de
- {
- struct drm_i915_private *dev_priv = dev->dev_private;
- + drm_kms_helper_poll_disable(dev);
- +
- pci_save_state(dev->pdev);
- /* If KMS is active, we do the leavevt stuff here */
- @@ -284,7 +286,8 @@ int i915_suspend(struct drm_device *dev,
- if (state.event == PM_EVENT_PRETHAW)
- return 0;
- - drm_kms_helper_poll_disable(dev);
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- + return 0;
- error = i915_drm_freeze(dev);
- if (error)
- @@ -332,6 +335,9 @@ int i915_resume(struct drm_device *dev)
- {
- int ret;
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- + return 0;
- +
- if (pci_enable_device(dev->pdev))
- return -EIO;
- @@ -523,6 +529,9 @@ static int i915_pm_suspend(struct device
- return -ENODEV;
- }
- + if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- + return 0;
- +
- error = i915_drm_freeze(drm_dev);
- if (error)
- return error;
- diff -urNp linux-2.6.37//drivers/gpu/drm/i915/intel_acpi.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/intel_acpi.c
- --- linux-2.6.37//drivers/gpu/drm/i915/intel_acpi.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/i915/intel_acpi.c 2011-01-15 14:53:53.000000000 -0200
- @@ -182,8 +182,12 @@ static void intel_dsm_platform_mux_info(
- DRM_DEBUG_DRIVER(" hpd mux info: %s\n",
- intel_dsm_mux_type(info->buffer.pointer[3]));
- }
- + } else if (pkg->type == ACPI_TYPE_BUFFER) {
- + DRM_ERROR("MUX INFO returned buffer %d %p\n", pkg->buffer.length, pkg->buffer.pointer);
- + if (pkg->buffer.length == 4)
- + DRM_ERROR("returned %08x\n", *(uint32_t *)pkg->buffer.pointer);
- } else {
- - DRM_ERROR("MUX INFO call failed\n");
- + DRM_ERROR("MUX INFO call failed %d\n", pkg->type);
- }
- out:
- diff -urNp linux-2.6.37//drivers/gpu/drm/nouveau/Kconfig linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/Kconfig
- --- linux-2.6.37//drivers/gpu/drm/nouveau/Kconfig 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/Kconfig 2011-01-15 15:03:23.000000000 -0200
- @@ -11,6 +11,7 @@ config DRM_NOUVEAU
- select FRAMEBUFFER_CONSOLE if !EMBEDDED
- select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT
- select ACPI_VIDEO if ACPI
- + select MXM_WMI if ACPI
- help
- Choose this option for open-source nVidia support.
- diff -urNp linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_acpi.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_acpi.c
- --- linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_acpi.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_acpi.c 2011-01-15 15:44:50.000000000 -0200
- @@ -4,6 +4,8 @@
- #include <acpi/acpi_drivers.h>
- #include <acpi/acpi_bus.h>
- #include <acpi/video.h>
- +#include <acpi/acpi.h>
- +#include <linux/mxm-wmi.h>
- #include "drmP.h"
- #include "drm.h"
- @@ -92,20 +94,13 @@ static int nouveau_dsm(acpi_handle handl
- static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
- {
- + int output_id = 0;
- + //hack output id using acpi lcd id
- + //sony vaio 0x80010100
- + mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0, output_id);
- return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL);
- }
- -static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
- -{
- - int arg;
- - if (state == VGA_SWITCHEROO_ON)
- - arg = NOUVEAU_DSM_POWER_SPEED;
- - else
- - arg = NOUVEAU_DSM_POWER_STAMINA;
- - nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL);
- - return 0;
- -}
- -
- static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
- {
- if (id == VGA_SWITCHEROO_IGD)
- @@ -114,15 +109,6 @@ static int nouveau_dsm_switchto(enum vga
- return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
- }
- -static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
- - enum vga_switcheroo_state state)
- -{
- - if (id == VGA_SWITCHEROO_IGD)
- - return 0;
- -
- - return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
- -}
- -
- static int nouveau_dsm_init(void)
- {
- return 0;
- @@ -130,15 +116,19 @@ static int nouveau_dsm_init(void)
- static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
- {
- - if (nouveau_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
- + /* easy option one - intel vendor ID means Integrated */
- + if (pdev->vendor == PCI_VENDOR_ID_INTEL)
- return VGA_SWITCHEROO_IGD;
- - else
- - return VGA_SWITCHEROO_DIS;
- +
- + /* is this device on Bus 0? - this may need improving */
- + if (pdev->bus->number == 0)
- + return VGA_SWITCHEROO_IGD;
- +
- + return VGA_SWITCHEROO_DIS;
- }
- static struct vga_switcheroo_handler nouveau_dsm_handler = {
- .switchto = nouveau_dsm_switchto,
- - .power_state = nouveau_dsm_power_state,
- .init = nouveau_dsm_init,
- .get_client_id = nouveau_dsm_get_client_id,
- };
- @@ -175,6 +165,14 @@ static bool nouveau_dsm_detect(void)
- struct pci_dev *pdev = NULL;
- int has_dsm = 0;
- int vga_count = 0;
- + bool guid_valid;
- +
- + /* lookup the GUID */
- + guid_valid = mxm_wmi_supported();
- + if (!guid_valid)
- + return false;
- +
- + printk("MXM GUID detected in BIOS\n");
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
- vga_count++;
- diff -urNp linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_drv.c
- --- linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_drv.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_drv.c 2011-01-15 15:17:35.000000000 -0200
- @@ -167,6 +167,9 @@ nouveau_pci_suspend(struct pci_dev *pdev
- if (pm_state.event == PM_EVENT_PRETHAW)
- return 0;
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- + return 0;
- +
- NV_INFO(dev, "Disabling fbcon acceleration...\n");
- nouveau_fbcon_save_disable_accel(dev);
- @@ -263,6 +266,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
- struct drm_crtc *crtc;
- int ret, i;
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- + return 0;
- +
- nouveau_fbcon_save_disable_accel(dev);
- NV_INFO(dev, "We're back, enabling device...\n");
- diff -urNp linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_drv.h
- --- linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_drv.h 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_drv.h 2011-01-15 15:18:35.000000000 -0200
- @@ -686,6 +686,8 @@ struct drm_nouveau_private {
- struct nouveau_fbdev *nfbdev;
- struct apertures_struct *apertures;
- +
- + bool powered_down;
- };
- static inline struct drm_nouveau_private *
- diff -urNp linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_state.c
- --- linux-2.6.37//drivers/gpu/drm/nouveau/nouveau_state.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/nouveau/nouveau_state.c 2011-01-15 15:38:42.000000000 -0200
- @@ -531,15 +531,25 @@ static void nouveau_switcheroo_set_state
- pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
- if (state == VGA_SWITCHEROO_ON) {
- printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- nouveau_pci_resume(pdev);
- drm_kms_helper_poll_enable(dev);
- + dev->switch_power_state = DRM_SWITCH_POWER_ON;
- } else {
- printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- drm_kms_helper_poll_disable(dev);
- nouveau_pci_suspend(pdev, pmm);
- + dev->switch_power_state = DRM_SWITCH_POWER_OFF;
- }
- }
- +static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
- +{
- + struct drm_device *dev = pci_get_drvdata(pdev);
- + nouveau_fbcon_output_poll_changed(dev);
- +}
- +
- static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
- {
- struct drm_device *dev = pci_get_drvdata(pdev);
- @@ -560,6 +570,7 @@ nouveau_card_init(struct drm_device *dev
- vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
- vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
- + nouveau_switcheroo_reprobe,
- nouveau_switcheroo_can_switch);
- /* Initialise internal driver API hooks */
- @@ -980,6 +991,7 @@ err_out:
- void nouveau_lastclose(struct drm_device *dev)
- {
- + vga_switcheroo_process_delayed_switch();
- }
- int nouveau_unload(struct drm_device *dev)
- diff -urNp linux-2.6.37//drivers/gpu/drm/radeon/radeon_device.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon_device.c
- --- linux-2.6.37//drivers/gpu/drm/radeon/radeon_device.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon_device.c 2011-01-15 15:23:55.000000000 -0200
- @@ -636,20 +636,20 @@ void radeon_check_arguments(struct radeo
- static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
- {
- struct drm_device *dev = pci_get_drvdata(pdev);
- - struct radeon_device *rdev = dev->dev_private;
- pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
- if (state == VGA_SWITCHEROO_ON) {
- printk(KERN_INFO "radeon: switched on\n");
- /* don't suspend or resume card normally */
- - rdev->powered_down = false;
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- radeon_resume_kms(dev);
- + dev->switch_power_state = DRM_SWITCH_POWER_ON;
- drm_kms_helper_poll_enable(dev);
- } else {
- printk(KERN_INFO "radeon: switched off\n");
- drm_kms_helper_poll_disable(dev);
- + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- radeon_suspend_kms(dev, pmm);
- - /* don't suspend or resume card normally */
- - rdev->powered_down = true;
- + dev->switch_power_state = DRM_SWITCH_POWER_OFF;
- }
- }
- @@ -773,6 +773,7 @@ int radeon_device_init(struct radeon_dev
- vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
- vga_switcheroo_register_client(rdev->pdev,
- radeon_switcheroo_set_state,
- + NULL,
- radeon_switcheroo_can_switch);
- r = radeon_init(rdev);
- @@ -835,7 +836,7 @@ int radeon_suspend_kms(struct drm_device
- }
- rdev = dev->dev_private;
- - if (rdev->powered_down)
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- return 0;
- /* turn off display hw */
- @@ -893,7 +894,7 @@ int radeon_resume_kms(struct drm_device
- struct drm_connector *connector;
- struct radeon_device *rdev = dev->dev_private;
- - if (rdev->powered_down)
- + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
- return 0;
- acquire_console_sem();
- diff -urNp linux-2.6.37//drivers/gpu/drm/radeon/radeon.h linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon.h
- --- linux-2.6.37//drivers/gpu/drm/radeon/radeon.h 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon.h 2011-01-15 15:21:15.000000000 -0200
- @@ -1110,7 +1110,6 @@ struct radeon_device {
- uint8_t audio_status_bits;
- uint8_t audio_category_code;
- - bool powered_down;
- struct notifier_block acpi_nb;
- /* only one userspace can use Hyperz features at a time */
- struct drm_file *hyperz_filp;
- diff -urNp linux-2.6.37//drivers/gpu/drm/radeon/radeon_kms.c linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon_kms.c
- --- linux-2.6.37//drivers/gpu/drm/radeon/radeon_kms.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/drm/radeon/radeon_kms.c 2011-01-15 15:24:36.000000000 -0200
- @@ -203,10 +203,6 @@ int radeon_info_ioctl(struct drm_device
- */
- int radeon_driver_firstopen_kms(struct drm_device *dev)
- {
- - struct radeon_device *rdev = dev->dev_private;
- -
- - if (rdev->powered_down)
- - return -EINVAL;
- return 0;
- }
- diff -urNp linux-2.6.37//drivers/gpu/vga/vgaarb.c linux-2.6.37-OPTIMUS//drivers/gpu/vga/vgaarb.c
- --- linux-2.6.37//drivers/gpu/vga/vgaarb.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/vga/vgaarb.c 2011-01-15 15:34:05.000000000 -0200
- @@ -62,6 +62,7 @@ struct vga_device {
- unsigned int io_norm_cnt; /* normal IO count */
- unsigned int mem_norm_cnt; /* normal MEM count */
- + bool bridge_has_one_vga;
- /* allow IRQ enable/disable hook */
- void *cookie;
- void (*irq_set_state)(void *cookie, bool enable);
- @@ -165,6 +166,8 @@ static struct vga_device *__vga_tryget(s
- unsigned int wants, legacy_wants, match;
- struct vga_device *conflict;
- unsigned int pci_bits;
- + u32 flags = 0;
- +
- /* Account for "normal" resources to lock. If we decode the legacy,
- * counterpart, we need to request it as well
- */
- @@ -237,16 +240,22 @@ static struct vga_device *__vga_tryget(s
- /* looks like he doesn't have a lock, we can steal
- * them from him
- */
- - vga_irq_set_state(conflict, false);
- + flags = 0;
- pci_bits = 0;
- - if (lwants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
- - pci_bits |= PCI_COMMAND_MEMORY;
- - if (lwants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
- - pci_bits |= PCI_COMMAND_IO;
- -
- - pci_set_vga_state(conflict->pdev, false, pci_bits,
- - change_bridge);
- + if (!conflict->bridge_has_one_vga) {
- + vga_irq_set_state(conflict, false);
- + flags |= PCI_VGA_STATE_CHANGE_DECODES;
- + if (lwants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
- + pci_bits |= PCI_COMMAND_MEMORY;
- + if (lwants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
- + pci_bits |= PCI_COMMAND_IO;
- + }
- +
- + if (change_bridge)
- + flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
- +
- + pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
- conflict->owns &= ~lwants;
- /* If he also owned non-legacy, that is no longer the case */
- if (lwants & VGA_RSRC_LEGACY_MEM)
- @@ -261,14 +270,23 @@ enable_them:
- * also have in "decodes". We can lock resources we don't decode but
- * not own them.
- */
- + flags = 0;
- pci_bits = 0;
- - if (wants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
- - pci_bits |= PCI_COMMAND_MEMORY;
- - if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
- - pci_bits |= PCI_COMMAND_IO;
- - pci_set_vga_state(vgadev->pdev, true, pci_bits, !!(wants & VGA_RSRC_LEGACY_MASK));
- -
- - vga_irq_set_state(vgadev, true);
- + if (!vgadev->bridge_has_one_vga) {
- + flags |= PCI_VGA_STATE_CHANGE_DECODES;
- + if (wants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
- + pci_bits |= PCI_COMMAND_MEMORY;
- + if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
- + pci_bits |= PCI_COMMAND_IO;
- + }
- + if (!!(wants & VGA_RSRC_LEGACY_MASK))
- + flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
- +
- + pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
- +
- + if (!vgadev->bridge_has_one_vga) {
- + vga_irq_set_state(vgadev, true);
- + }
- vgadev->owns |= (wants & vgadev->decodes);
- lock_them:
- vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
- @@ -421,6 +439,62 @@ bail:
- }
- EXPORT_SYMBOL(vga_put);
- +/* Rules for using a bridge to control a VGA descendant decoding:
- + if a bridge has only one VGA descendant then it can be used
- + to control the VGA routing for that device.
- + It should always use the bridge closest to the device to control it.
- + If a bridge has a direct VGA descendant, but also have a sub-bridge
- + VGA descendant then we cannot use that bridge to control the direct VGA descendant.
- + So for every device we register, we need to iterate all its parent bridges
- + so we can invalidate any devices using them properly.
- +*/
- +static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
- +{
- + struct vga_device *same_bridge_vgadev;
- + struct pci_bus *new_bus, *bus;
- + struct pci_dev *new_bridge, *bridge;
- +
- + vgadev->bridge_has_one_vga = true;
- +
- + if (list_empty(&vga_list))
- + return;
- +
- + /* okay iterate the new devices bridge hierarachy */
- + new_bus = vgadev->pdev->bus;
- + while (new_bus) {
- + new_bridge = new_bus->self;
- +
- + if (new_bridge) {
- + /* go through list of devices already registered */
- + list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
- + bus = same_bridge_vgadev->pdev->bus;
- + bridge = bus->self;
- +
- + /* see if the share a bridge with this device */
- + if (new_bridge == bridge) {
- + /* if their direct parent bridge is the same
- + as any bridge of this device then it can't be used
- + for that device */
- + same_bridge_vgadev->bridge_has_one_vga = false;
- + }
- +
- + /* now iterate the previous devices bridge hierarchy */
- + /* if the new devices parent bridge is in the other devices
- + hierarchy then we can't use it to control this device */
- + while (bus) {
- + bridge = bus->self;
- + if (bridge) {
- + if (bridge == vgadev->pdev->bus->self)
- + vgadev->bridge_has_one_vga = false;
- + }
- + bus = bus->parent;
- + }
- + }
- + }
- + new_bus = new_bus->parent;
- + }
- +}
- +
- /*
- * Currently, we assume that the "initial" setup of the system is
- * not sane, that is we come up with conflicting devices and let
- @@ -500,6 +574,8 @@ static bool vga_arbiter_add_pci_device(s
- vga_default = pci_dev_get(pdev);
- #endif
- + vga_arbiter_check_bridge_sharing(vgadev);
- +
- /* Add to the list */
- list_add(&vgadev->list, &vga_list);
- vga_count++;
- @@ -1222,6 +1298,7 @@ static int __init vga_arb_device_init(vo
- {
- int rc;
- struct pci_dev *pdev;
- + struct vga_device *vgadev;
- rc = misc_register(&vga_arb_device);
- if (rc < 0)
- @@ -1238,6 +1315,13 @@ static int __init vga_arb_device_init(vo
- vga_arbiter_add_pci_device(pdev);
- pr_info("vgaarb: loaded\n");
- +
- + list_for_each_entry(vgadev, &vga_list, list) {
- + if (vgadev->bridge_has_one_vga)
- + pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev));
- + else
- + pr_info("vgaarb: no bridge control possible %s\n", pci_name(vgadev->pdev));
- + }
- return rc;
- }
- subsys_initcall(vga_arb_device_init);
- diff -urNp linux-2.6.37//drivers/gpu/vga/vga_switcheroo.c linux-2.6.37-OPTIMUS//drivers/gpu/vga/vga_switcheroo.c
- --- linux-2.6.37//drivers/gpu/vga/vga_switcheroo.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/gpu/vga/vga_switcheroo.c 2011-01-15 15:43:37.000000000 -0200
- @@ -33,6 +33,7 @@ struct vga_switcheroo_client {
- struct fb_info *fb_info;
- int pwr_state;
- void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
- + void (*reprobe)(struct pci_dev *pdev);
- bool (*can_switch)(struct pci_dev *pdev);
- int id;
- bool active;
- @@ -103,6 +104,7 @@ static void vga_switcheroo_enable(void)
- int vga_switcheroo_register_client(struct pci_dev *pdev,
- void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
- + void (*reprobe)(struct pci_dev *pdev),
- bool (*can_switch)(struct pci_dev *pdev))
- {
- int index;
- @@ -117,6 +119,7 @@ int vga_switcheroo_register_client(struc
- vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
- vgasr_priv.clients[index].pdev = pdev;
- vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
- + vgasr_priv.clients[index].reprobe = reprobe;
- vgasr_priv.clients[index].can_switch = can_switch;
- vgasr_priv.clients[index].id = -1;
- if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
- @@ -174,7 +177,8 @@ static int vga_switcheroo_show(struct se
- int i;
- mutex_lock(&vgasr_mutex);
- for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
- - seq_printf(m, "%d:%c:%s:%s\n", i,
- + seq_printf(m, "%d:%s:%c:%s:%s\n", i,
- + vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
- vgasr_priv.clients[i].active ? '+' : ' ',
- vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
- pci_name(vgasr_priv.clients[i].pdev));
- @@ -190,9 +194,8 @@ static int vga_switcheroo_debugfs_open(s
- static int vga_switchon(struct vga_switcheroo_client *client)
- {
- - int ret;
- -
- - ret = vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
- + if (vgasr_priv.handler->power_state)
- + vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
- /* call the driver callback to turn on device */
- client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
- client->pwr_state = VGA_SWITCHEROO_ON;
- @@ -203,12 +206,14 @@ static int vga_switchoff(struct vga_swit
- {
- /* call the driver callback to turn off device */
- client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
- - vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
- + if (vgasr_priv.handler->power_state)
- + vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
- client->pwr_state = VGA_SWITCHEROO_OFF;
- return 0;
- }
- -static int vga_switchto(struct vga_switcheroo_client *new_client)
- +/* stage one happens before delay */
- +static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
- {
- int ret;
- int i;
- @@ -235,10 +240,28 @@ static int vga_switchto(struct vga_switc
- vga_switchon(new_client);
- /* swap shadow resource to denote boot VGA device has changed so X starts on new device */
- - active->active = false;
- -
- active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
- new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
- + return 0;
- +}
- +
- +/* post delay */
- +static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
- +{
- + int ret;
- + int i;
- + struct vga_switcheroo_client *active = NULL;
- +
- + for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
- + if (vgasr_priv.clients[i].active == true) {
- + active = &vgasr_priv.clients[i];
- + break;
- + }
- + }
- + if (!active)
- + return 0;
- +
- + active->active = false;
- if (new_client->fb_info) {
- struct fb_event event;
- @@ -250,6 +273,9 @@ static int vga_switchto(struct vga_switc
- if (ret)
- return ret;
- + if (new_client->reprobe)
- + new_client->reprobe(new_client->pdev);
- +
- if (active->pwr_state == VGA_SWITCHEROO_ON)
- vga_switchoff(active);
- @@ -265,6 +291,7 @@ vga_switcheroo_debugfs_write(struct file
- const char *pdev_name;
- int i, ret;
- bool delay = false, can_switch;
- + bool just_mux = false;
- int client_id = -1;
- struct vga_switcheroo_client *client = NULL;
- @@ -319,6 +346,15 @@ vga_switcheroo_debugfs_write(struct file
- if (strncmp(usercmd, "DIS", 3) == 0)
- client_id = VGA_SWITCHEROO_DIS;
- + if (strncmp(usercmd, "MIGD", 3) == 0) {
- + just_mux = true;
- + client_id = VGA_SWITCHEROO_IGD;
- + }
- + if (strncmp(usercmd, "MDIS", 3) == 0) {
- + just_mux = true;
- + client_id = VGA_SWITCHEROO_DIS;
- + }
- +
- if (client_id == -1)
- goto out;
- @@ -330,6 +366,12 @@ vga_switcheroo_debugfs_write(struct file
- }
- vgasr_priv.delayed_switch_active = false;
- +
- + if (just_mux) {
- + ret = vgasr_priv.handler->switchto(client_id);
- + goto out;
- + }
- +
- /* okay we want a switch - test if devices are willing to switch */
- can_switch = true;
- for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
- @@ -345,18 +387,21 @@ vga_switcheroo_debugfs_write(struct file
- if (can_switch == true) {
- pdev_name = pci_name(client->pdev);
- - ret = vga_switchto(client);
- + ret = vga_switchto_stage1(client);
- + if (ret)
- + printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
- +
- + ret = vga_switchto_stage2(client);
- if (ret)
- - printk(KERN_ERR "vga_switcheroo: switching failed %d\n", ret);
- ++ printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
- } else {
- printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
- vgasr_priv.delayed_switch_active = true;
- vgasr_priv.delayed_client_id = client_id;
- - /* we should at least power up the card to
- - make the switch faster */
- - if (client->pwr_state == VGA_SWITCHEROO_OFF)
- - vga_switchon(client);
- + ret = vga_switchto_stage1(client);
- + if (ret)
- + printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
- }
- out:
- @@ -438,9 +483,9 @@ int vga_switcheroo_process_delayed_switc
- goto err;
- pdev_name = pci_name(client->pdev);
- - ret = vga_switchto(client);
- + ret = vga_switchto_stage2(client);
- if (ret)
- - printk(KERN_ERR "vga_switcheroo: delayed switching failed %d\n", ret);
- + printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
- vgasr_priv.delayed_switch_active = false;
- err = 0;
- diff -urNp linux-2.6.37//drivers/pci/pci.c linux-2.6.37-OPTIMUS//drivers/pci/pci.c
- --- linux-2.6.37//drivers/pci/pci.c 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/pci/pci.c 2011-01-15 15:36:29.000000000 -0200
- @@ -2888,31 +2888,34 @@ static int pci_set_vga_state_arch(struct
- * @dev: the PCI device
- * @decode: true = enable decoding, false = disable decoding
- * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
- - * @change_bridge: traverse ancestors and change bridges
- + * @change_bridge_flags: traverse ancestors and change bridges
- + * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE
- */
- int pci_set_vga_state(struct pci_dev *dev, bool decode,
- - unsigned int command_bits, bool change_bridge)
- + unsigned int command_bits, u32 flags)
- {
- struct pci_bus *bus;
- struct pci_dev *bridge;
- u16 cmd;
- int rc;
- - WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
- + WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) & (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)));
- /* ARCH specific VGA enables */
- - rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
- + rc = pci_set_vga_state_arch(dev, decode, command_bits, flags);
- if (rc)
- return rc;
- - pci_read_config_word(dev, PCI_COMMAND, &cmd);
- - if (decode == true)
- - cmd |= command_bits;
- - else
- - cmd &= ~command_bits;
- - pci_write_config_word(dev, PCI_COMMAND, cmd);
- + if (flags & PCI_VGA_STATE_CHANGE_DECODES) {
- + pci_read_config_word(dev, PCI_COMMAND, &cmd);
- + if (decode == true)
- + cmd |= command_bits;
- + else
- + cmd &= ~command_bits;
- + pci_write_config_word(dev, PCI_COMMAND, cmd);
- + }
- - if (change_bridge == false)
- + if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE))
- return 0;
- bus = dev->bus;
- diff -urNp linux-2.6.37//drivers/platform/x86/Kconfig linux-2.6.37-OPTIMUS//drivers/platform/x86/Kconfig
- --- linux-2.6.37//drivers/platform/x86/Kconfig 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/platform/x86/Kconfig 2011-01-15 14:54:56.000000000 -0200
- @@ -639,4 +639,11 @@ config XO1_RFKILL
- Support for enabling/disabling the WLAN interface on the OLPC XO-1
- laptop.
- +config MXM_WMI
- + tristate "WMI support for MXM Laptop Graphics"
- + depends on WMI
- + ---help---
- + MXM is a standard for laptop graphics cards, the WMI interface
- + is required for switchable nvidia graphics machines
- +
- endif # X86_PLATFORM_DEVICES
- diff -urNp linux-2.6.37//drivers/platform/x86/Makefile linux-2.6.37-OPTIMUS//drivers/platform/x86/Makefile
- --- linux-2.6.37//drivers/platform/x86/Makefile 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//drivers/platform/x86/Makefile 2011-01-15 14:55:33.000000000 -0200
- @@ -33,3 +33,4 @@ obj-$(CONFIG_INTEL_IPS) += intel_ips.o
- obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
- obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o
- obj-$(CONFIG_IBM_RTL) += ibm_rtl.o
- +obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
- diff -urNp linux-2.6.37//drivers/platform/x86/mxm-wmi.c linux-2.6.37-OPTIMUS//drivers/platform/x86/mxm-wmi.c
- --- linux-2.6.37//drivers/platform/x86/mxm-wmi.c 1969-12-31 21:00:00.000000000 -0300
- +++ linux-2.6.37-OPTIMUS//drivers/platform/x86/mxm-wmi.c 2011-01-15 15:45:34.000000000 -0200
- @@ -0,0 +1,85 @@
- +/*
- + * MXM WMI driver
- + *
- + * Copyright(C) 2010 Red Hat.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- +*/
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/init.h>
- +#include <acpi/acpi_bus.h>
- +#include <acpi/acpi_drivers.h>
- +
- +MODULE_AUTHOR("Dave Airlie");
- +MODULE_DESCRIPTION("MXM WMI Driver");
- +MODULE_LICENSE("GPL");
- +
- +#define MXM_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
- +
- +MODULE_ALIAS("wmi:"MXM_WMMX_GUID);
- +
- +#define MXM_WMMX_FUNC_MXDS 0x5344584D /* "MXDS" */
- +
- +struct mxds_args {
- + u32 func;
- + u32 args;
- + u32 xarg;
- +};
- +
- +int mxm_wmi_call_mxds(int adapter, uint32_t output_id)
- +{
- + struct mxds_args args = {
- + .func = MXM_WMMX_FUNC_MXDS,
- + .args = output_id,
- + .xarg = 1,
- + };
- + struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
- + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- + acpi_status status;
- +
- + printk("calling mux switch %d\n", adapter);
- +
- + status = wmi_evaluate_method(MXM_WMMX_GUID, 0x1, adapter, &input,
- + &output);
- +
- + if (ACPI_FAILURE(status))
- + return status;
- +
- + printk("mux switched %d\n", status);
- + return 0;
- +
- +}
- +EXPORT_SYMBOL_GPL(mxm_wmi_call_mxds);
- +
- +bool mxm_wmi_supported(void)
- +{
- + bool guid_valid;
- + guid_valid = wmi_has_guid(MXM_WMMX_GUID);
- + return guid_valid;
- +}
- +EXPORT_SYMBOL_GPL(mxm_wmi_supported);
- +
- +static int __init mxm_wmi_init(void)
- +{
- + return 0;
- +}
- +
- +static void __exit mxm_wmi_exit(void)
- +{
- +}
- +
- +module_init(mxm_wmi_init);
- +module_exit(mxm_wmi_exit);
- Os arquivos binários linux-2.6.37//drivers/staging/ft1000/ft1000-pcmcia/ft1000.img e linux-2.6.37-OPTIMUS//drivers/staging/ft1000/ft1000-pcmcia/ft1000.img são diferentes
- Os arquivos binários linux-2.6.37//drivers/staging/ft1000/ft1000-usb/ft3000.img e linux-2.6.37-OPTIMUS//drivers/staging/ft1000/ft1000-usb/ft3000.img são diferentes
- diff -urNp linux-2.6.37//include/drm/drmP.h linux-2.6.37-OPTIMUS//include/drm/drmP.h
- --- linux-2.6.37//include/drm/drmP.h 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//include/drm/drmP.h 2011-01-15 15:25:49.000000000 -0200
- @@ -1044,9 +1044,13 @@ struct drm_device {
- uint32_t invalidate_domains; /* domains pending invalidation */
- uint32_t flush_domains; /* domains pending flush */
- /*@} */
- -
- + int switch_power_state;
- };
- +#define DRM_SWITCH_POWER_ON 0
- +#define DRM_SWITCH_POWER_OFF 1
- +#define DRM_SWITCH_POWER_CHANGING 2
- +
- static __inline__ int drm_core_check_feature(struct drm_device *dev,
- int feature)
- {
- diff -urNp linux-2.6.37//include/linux/mxm-wmi.h linux-2.6.37-OPTIMUS//include/linux/mxm-wmi.h
- --- linux-2.6.37//include/linux/mxm-wmi.h 1969-12-31 21:00:00.000000000 -0300
- +++ linux-2.6.37-OPTIMUS//include/linux/mxm-wmi.h 2011-01-15 15:46:03.000000000 -0200
- @@ -0,0 +1,32 @@
- +/*
- + * MXM WMI driver
- + *
- + * Copyright(C) 2010 Red Hat.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- +*/
- +
- +#ifndef MXM_WMI_H
- +#define MXM_WMI_H
- +
- +/* discrete adapters */
- +#define MXM_MXDS_ADAPTER_0 0x0
- +#define MXM_MXDS_ADAPTER_1 0x0
- +/* integrated adapter */
- +#define MXM_MXDS_ADAPTER_IGD 0x10
- +int mxm_wmi_call_mxds(int adapter, u32 output_id);
- +bool mxm_wmi_supported(void);
- +
- +#endif
- diff -urNp linux-2.6.37//include/linux/pci.h linux-2.6.37-OPTIMUS//include/linux/pci.h
- --- linux-2.6.37//include/linux/pci.h 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//include/linux/pci.h 2011-01-15 15:37:50.000000000 -0200
- @@ -916,8 +916,11 @@ int pci_cfg_space_size_ext(struct pci_de
- int pci_cfg_space_size(struct pci_dev *dev);
- unsigned char pci_bus_max_busnr(struct pci_bus *bus);
- +#define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
- +#define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)
- +
- int pci_set_vga_state(struct pci_dev *pdev, bool decode,
- - unsigned int command_bits, bool change_bridge);
- + unsigned int command_bits, u32 flags);
- /* kmem_cache style wrapper around pci_alloc_consistent() */
- #include <linux/pci-dma.h>
- @@ -1047,7 +1050,7 @@ static inline int pci_proc_domain(struct
- /* some architectures require additional setup to direct VGA traffic */
- typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
- - unsigned int command_bits, bool change_bridge);
- + unsigned int command_bits, u32 flags);
- extern void pci_register_set_vga_state(arch_set_vga_state_t func);
- #else /* CONFIG_PCI is not enabled */
- diff -urNp linux-2.6.37//include/linux/vga_switcheroo.h linux-2.6.37-OPTIMUS//include/linux/vga_switcheroo.h
- --- linux-2.6.37//include/linux/vga_switcheroo.h 2011-01-04 22:50:19.000000000 -0200
- +++ linux-2.6.37-OPTIMUS//include/linux/vga_switcheroo.h 2011-01-15 15:11:26.000000000 -0200
- @@ -33,6 +33,7 @@ struct vga_switcheroo_handler {
- void vga_switcheroo_unregister_client(struct pci_dev *dev);
- int vga_switcheroo_register_client(struct pci_dev *dev,
- void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state),
- + void (*reprobe)(struct pci_dev *dev),
- bool (*can_switch)(struct pci_dev *dev));
- void vga_switcheroo_client_fb_set(struct pci_dev *dev,
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement