Fixing X220 Video The Right Way
John Baldwin
jhb at freebsd.org
Fri Jun 14 16:03:38 UTC 2013
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 at 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 at 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 at 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
More information about the freebsd-current
mailing list