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>