Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Jun 2013 11:39:16 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        matt <sendtomatt@gmail.com>
Cc:        Adrian Chadd <adrian@freebsd.org>, freebsd-current@freebsd.org, freebsd-acpi@freebsd.org
Subject:   Re: Fixing X220 Video The Right Way
Message-ID:  <201306141139.16728.jhb@freebsd.org>
In-Reply-To: <51394952.9030700@gmail.com>
References:  <512A6FFF.2060603@gmail.com> <201302281209.45170.jhb@freebsd.org> <51394952.9030700@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thursday, March 07, 2013 9:13:38 pm matt wrote:
> On 02/28/13 09:09, John Baldwin wrote:
> > On Thursday, February 28, 2013 8:15:46 am matt wrote:
> >> On 02/27/13 12:27, John Baldwin wrote:
> >>> On Wednesday, February 27, 2013 1:35:43 pm matt wrote:
> >>>> On 02/27/13 09:00, John Baldwin wrote:
> >>>>> If that is true, it's because your BIOS is lying. Do you have a URL to
> >>>>> your ASL lying around already?
> >>>> Too big for pastebin :( +500k
> >>>>
> >>>> 
https://docs.google.com/file/d/0B6YlMzJxarGbVnotLUdNWWNTVG8/edit?usp=sharing
> >>> Here is where I find _DOD and _DOS methods:
> >>>
> >>>          Device (PCI0)
> >>>              Device (VID)
> >>>                  Name (_ADR, 0x00020000)  // _ADR: Address
> >>>                  Method (_DOS, 1, NotSerialized)  // _DOS: Disable 
Output Switching
> >>>                  Method (_DOD, 0, NotSerialized)  // _DOD: Display 
Output Devices
> >>>              Device (PEG)
> >>>                  Name (_ADR, 0x00010000)  // _ADR: Address
> >>>                  Device (VID)
> >>>                      Name (_ADR, 0x00)  // _ADR: Address
> >>>                      Method (_DOS, 1, NotSerialized)  // _DOS: Disable 
Output Switching
> >>>                      Method (_DOD, 0, NotSerialized)  // _DOD: Display 
Output Devices
> >>>
> >>> PCI0.VID is a PCI device at pci0:0:2:0.
> >>> PCI0.PEG would be a PCI-PCI bridge at pci0:0:1:0.
> >>> It would have a child device at 0:0 that would be PCI0.PEG.VID.  Does 
the X220
> >>> have a switchable GPU (e.g. it has built-in Intel graphics, but also has 
an
> >>> Nvidia GPU or some such?).  If so, I imagine that PCI0.VID is the Intel 
graphics
> >>> and PEG is the non-Intel.  The output of 'pciconf -lcv' would be useful 
to determine
> >>> that.  If both PCI devices exist you shoudl have both acpi_video0 and 
acpi_video1.
> >>> However, it may be that the acpi_video driver doesn't cope well with 
having multiple
> >>> devices.
> >> Only Intel graphics, there is no option for switchable graphics.
> >> I initially thought that PEG was for Optimus usage, and left in the bios 
> >> by accident (i.e. Lenovo using a generic DSDT for many machines)
> >>
> >> Here is pciconf -lcf, truncated
> >> hostb0@pci0:0:0:0:    class=0x060000 card=0x21da17aa chip=0x01048086 
> >> rev=0x09 hdr=0x00
> >>      vendor     = 'Intel Corporation'
> >>      device     = '2nd Generation Core Processor Family DRAM Controller'
> >>      class      = bridge
> >>      subclass   = HOST-PCI
> >>      cap 09[e0] = vendor (length 12) Intel cap 0 version 1
> >> vgapci0@pci0:0:2:0:    class=0x030000 card=0x21da17aa chip=0x01268086 
> >> rev=0x09 hdr=0x00
> >>      vendor     = 'Intel Corporation'
> >>      device     = '2nd Generation Core Processor Family Integrated 
> >> Graphics Controller'
> >>      class      = display
> >>      subclass   = VGA
> >>      cap 05[90] = MSI supports 1 message enabled with 1 message
> >>      cap 01[d0] = powerspec 2  supports D0 D3  current D0
> >>      cap 13[a4] = PCI Advanced Features: FLR TP
> >> none0@pci0:0:22:0:    class=0x078000 card=0x21da17aa chip=0x1c3a8086 
> >> rev=0x04 hdr=0x00
> >>      vendor     = 'Intel Corporation'
> >>
> >> As you can see there is no device at pci0:0:1:0. So no dev_t with for 
> >> acpi_video to probe or attach to.
> >>
> >> Nonetheless, only PEGs ACPI methods work, which is quite broken. This is 
> >> true for a large number of Lenovo devices, back to x61 (non-attaching 
> >> AGP adr) and probably including some other x series and t series.
> >>
> >> Unfortunately the ASL will not compile which makes fixing the DSDT an 
> >> exercise in fixing broken ACPI.
> >>
> >> What I find interesting is that as far as I can tell, there's no special 
> >> case handling for this device in Linux, yet backlight controls work out 
> >> of the box since about 3.0. Installing Linux as the OSI via loader.conf 
> >> is not the issue, unfortunately, nor Windows 2006 (/WVIS) or Windows 
> >> 2009 (/WIN7). I get correct (for platform) behavior when I call PEGs 
> >> _BCM... :(
> >>
> >> Is Linux getting this to work by doing it wrong, essentially?
> > Yes.  I think the best way to fix this is to add a way to specify a
> > hint to override the ACPI path associated with a PCI device.  Something
> > like:
> >
> > hw.pci0.0.2.0.handle="\_SB_.PCI0.PEG.VID"
> >
> > I think this patch should do the trick:
> >
> > Index: sys/dev/acpica/acpi_pci.c
> > ===================================================================
> > --- acpi_pci.c	(revision 247320)
> > +++ acpi_pci.c	(working copy)
> > @@ -264,6 +264,40 @@ acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 le
> >  	return_ACPI_STATUS (AE_OK);
> >  }
> >  
> > +static void
> > +acpi_pci_override_handles(device_t dev)
> > +{
> > +	struct acpi_pci_devinfo *dinfo;
> > +	device_t *devlist;
> > +	int error, i, numdevs;
> > +	char tunable_name[64], *path;
> > +	ACPI_HANDLE handle;
> > +
> > +	error = device_get_children(dev, &devlist, &numdevs);
> > +	if (error)
> > +		return;
> > +	for (i = 0; i < numdevs; i++) {
> > +		dinfo = device_get_ivars(devlist[i]);
> > +		snprintf(tunable_name, sizeof(tunable_name),
> > +		    "hw.pci%d.%d.%d.%d.handle", dinfo->ap_dinfo.cfg.domain,
> > +		    dinfo->ap_dinfo.cfg.bus, dinfo->ap_dinfo.cfg.slot,
> > +		    dinfo->ap_dinfo.cfg.func);
> > +		path = getenv(tunable_name);
> > +		if (path == NULL)
> > +			continue;
> > +		if (ACPI_SUCCESS(AcpiGetHandle(NULL, path, &handle))) {
> > +			device_printf(dev,
> > +			    "Forcing device at %d.%d to use path %s\n",
> > +			    dinfo->ap_dinfo.cfg.slot,
> > +			    dinfo->ap_dinfo.cfg.func, path);
> > +			dinfo->ap_handle = handle;
> > +			acpi_pci_update_device(handle, devlist[i]);
> > +		}
> > +		freeenv(path);
> > +	}
> > +	free(devlist, M_TEMP);
> > +}
> > +
> >  static int
> >  acpi_pci_probe(device_t dev)
> >  {
> > @@ -306,5 +340,10 @@ acpi_pci_attach(device_t dev)
> >  	AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
> >  	    acpi_pci_save_handle, NULL, dev, NULL);
> >  
> > +	/*
> > +	 * Perform another pass over child devices to allow their
> > +	 * handles to be overridden via a hint from the user.
> > +	 */
> > +	acpi_pci_override_handles(dev);
> >  	return (bus_generic_attach(dev));
> >  }
> >
> >
> I have been trying to get this patch to work. Basically I can't get a
> backslash into the appropriate variable, loader.conf seems to get them
> purged?
> 
> I've tried singlequotes, double backslash, etc...every time the path
> variable is _SB.PCI0.PEG.VID instead of \_SB.PCI0.PEG.VID
> 
> Is there a proper way to escape a backslash in loader.conf I'm missing?

I got this to work by using 4 backslashes.  At that point the patch worked.
(I recently got access to an X220.)  I get a local APIC error each time I
adjust the brightness though (probably the BIOS is doing something wonky).

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306141139.16728.jhb>