Created attachment 95161 [details] acpidump output Since kernel 3.7 I'm unable to control the brightness of the display backlight on my Dell Inspiron 15R SE (model number 7520) via ACPI methods. Neither using the hotkeys, nor manually writing values into /sys/class/backlight/acpi_video[0,1]/brightness changes the brightness. It works when either writing to intel_backlight/brightness or using kernel 3.6 or (the preinstalled) Windows 8. The actual commit that broke it was a57f7f9175b8ccbc9df83ac13860488913115de4 ( ACPICA: Add Windows8/Server2012 string for _OSI method). With that commit, _BCL exposes a 102 item list instead of an 18 item one, and _BQC always seems to return the value 100 (which is what breaks the brightness control via hotkey). I've attached the output of acpidump, which shows the differentiation in behaviour between Windows 8 and !Windows 8 done by the AML code; I don't speak AML fluently enough to interpret what exactly it's doing, though :(
*** This bug has been marked as a duplicate of bug 51231 ***
Some more details: - In Windows 8 mode, _BCL reports 102 levels (100, 30, and 1-100). - In that mode, I get 2 acpi_video devices instead of previously 1. - Executing _BCM in either output device succeeds, but doesn't have any visible effect. _BQC always returns '100' afterwards, no matter what value was written via _BCM
More findings: _BQC uses the CBLV variable as return value: Method (_BQC, 0, NotSerialized) { If (LEqual (OSYS, 0x07DC)) { Store (And (CBLV, 0xFF), Local0) Return (Local0) } Else [...] which is updated by the i915 driver after an ASLE interrupt. The AML has a AINT method which updates BCLP and triggers the interrupt, however, it's only called in the !Windows 8 case: Method (_BCM, 1, NotSerialized) { If (LEqual (OSYS, 0x07DC)) { Store (Arg0, ^^^LPCB.EC0.BRTS) Store (Arg0, BRTL) } Else { If (LAnd (LGreaterEqual (Arg0, Zero), LLessEqual (Arg0, 0x64))) { AINT (One, Arg0) Store (Arg0, BRTL) } } } In the Windows 8 case, only the BRTS variable in the EC is written, thus no interrupt, thus no CBLV update, thus _BQC always stays at the same value. Does BRTS have some special meaning that I've missed?
(In reply to comment #2) > Some more details: > > - In Windows 8 mode, _BCL reports 102 levels (100, 30, and 1-100). > - In that mode, I get 2 acpi_video devices instead of previously 1. You have 2 vga controllers? lspci please. > - Executing _BCM in either output device succeeds, but doesn't have any > visible > effect. _BQC always returns '100' afterwards, no matter what value was > written > via _BCM What about the values in device LCD's _BCL list, like 10,20,etc.?
Created attachment 95791 [details] Output of lspci -vv
(In reply to comment #4) > (In reply to comment #2) > > Some more details: > > > > - In Windows 8 mode, _BCL reports 102 levels (100, 30, and 1-100). > > - In that mode, I get 2 acpi_video devices instead of previously 1. > > You have 2 vga controllers? > lspci please. Yes, the processor-integrated one (which I'm using) and a Radeon 7730M (which I turned off via vgaswitcheroo). There's no mux involved, though, so only the Intel controller is driving the video outputs. lspci output attached. > > - Executing _BCM in either output device succeeds, but doesn't have any > visible > > effect. _BQC always returns '100' afterwards, no matter what value was > written > > via _BCM > > What about the values in device LCD's _BCL list, like 10,20,etc.? Doesn't help either. The !Windows 8 _BCL table looks like this: Name (BFHD, Package (0x12) { 0x64, 0x14, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28, 0x2D, 0x32, 0x38, 0x3F, 0x46, 0x4D, 0x55, 0x5C, 0x64 }) I've tried writing the following values: - 2 (to try one valid index) - 20 (a value present in _BCL) - 19 and 21 (to cover off-by-one errors in indexing)
(In reply to comment #3) > More findings: > > _BQC uses the CBLV variable as return value: > > Method (_BQC, 0, NotSerialized) > { > If (LEqual (OSYS, 0x07DC)) > { > Store (And (CBLV, 0xFF), Local0) > Return (Local0) > } > Else > [...] > > which is updated by the i915 driver after an ASLE interrupt. The AML has a > AINT > method which updates BCLP and triggers the interrupt, however, it's only > called > in the !Windows 8 case: That's interesting, how did you find this out? > > Method (_BCM, 1, NotSerialized) > { > If (LEqual (OSYS, 0x07DC)) > { > Store (Arg0, ^^^LPCB.EC0.BRTS) > Store (Arg0, BRTL) > } > Else > { > If (LAnd (LGreaterEqual (Arg0, Zero), LLessEqual > (Arg0, > 0x64))) > { > AINT (One, Arg0) > Store (Arg0, BRTL) > } > } > } > > In the Windows 8 case, only the BRTS variable in the EC is written, thus no > interrupt, thus no CBLV update, thus _BQC always stays at the same value. > Does > BRTS have some special meaning that I've missed? Perhaps only EC firmware writer knows that. I suppose on write to a variable in EC space, the EC firmware will do something accordingly, but I'm not sure.
(In reply to comment #7) > (In reply to comment #3) > > More findings: > > > > _BQC uses the CBLV variable as return value: > > which is updated by the i915 driver after an ASLE interrupt. The AML has a > AINT > > method which updates BCLP and triggers the interrupt, however, it's only > called > > in the !Windows 8 case: > > That's interesting, how did you find this out? By just looking around :) I - looked at the DSDT and saw it's using CBLV in _BQC - grepped the kernel source for CBLV - found drivers/gpu/drm/i915/intel_opregion.c - checked it, found that the CBLV update (and the actual brightness update, which is done in the same function - asle_set_backlight) is triggered by the ASLE interrupt and the BCLP value - grepped the DSDT for BCLP, found the AINT method which also sets ASLE - found that it's only used in the !Windows 8 case I verified this by adding debug statements in intel_opregion.c, which proved the expectations: In the !Windows 8 case, the ASLE interrupt is fired, CBLV (and the actual backlight brightness) are updated and everything works as intended. In the Windows 8 case, there's no ASLE interrupt, thus no CBLV update (which makes _BQC stuck) and no brightness update. > > In the Windows 8 case, only the BRTS variable in the EC is written, thus no > > interrupt, thus no CBLV update, thus _BQC always stays at the same value. > Does > > BRTS have some special meaning that I've missed? > > Perhaps only EC firmware writer knows that. > I suppose on write to a variable in EC space, the EC firmware will do > something > accordingly, but I'm not sure. OK. I was thinking from a spec perspective: Might it be that there's some new mechanism for backlight control introduced with Windows 8 that the kernel just doesn't implement yet?
BTW, FWIW, here's what dmesg says for the video module initialization in the Windows 8 case: [ 2.860620] [Firmware Bug]: ACPI(PEGP) defines _DOD but not _DOS [ 2.861506] acpi device:2d: registered as cooling_device8 [ 2.861646] ACPI: Video Device [PEGP] (multi-head: yes rom: no post: no) [ 2.861679] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2b/LNXVIDEO:00/input/input5 [ 2.861724] [Firmware Bug]: Duplicate ACPI video bus devices for the same VGA controller, please try module parameter "video.allow_duplicates=1"if the current driver doesn't work. [ 2.862467] acpi device:3c: registered as cooling_device9 [ 2.862609] ACPI: Video Device [GFX0] (multi-head: yes rom: no post: no) [ 2.862633] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:02/input/input6 Setting video.allow_duplicates=1 gives me a third acpi_video devices: [ 3.033037] [Firmware Bug]: ACPI(PEGP) defines _DOD but not _DOS [ 3.033936] acpi device:2d: registered as cooling_device8 [ 3.034076] ACPI: Video Device [PEGP] (multi-head: yes rom: no post: no) [ 3.034110] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2b/LNXVIDEO:00/input/input5 [ 3.034149] [Firmware Bug]: Duplicate ACPI video bus devices for the same VGA controller, please try module parameter "video.allow_duplicates=1"if the current driver doesn't work. [ 3.334109] acpi device:35: registered as cooling_device9 [ 3.334186] ACPI: Video Device [VGA] (multi-head: yes rom: no post: no) [ 3.334263] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2b/LNXVIDEO:01/input/input6 [ 3.336576] acpi device:3c: registered as cooling_device10 [ 3.336949] ACPI: Video Device [GFX0] (multi-head: yes rom: no post: no) [ 3.337024] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:02/input/input7 I can set values on this device (max_brightness is 9, I can set e.g. 5 and actual_brightness becomes 5, too), but the actual brightness of the backlight doesn't change when doing that.
(In reply to comment #9) > BTW, FWIW, here's what dmesg says for the video module initialization in the > Windows 8 case: > > [ 2.860620] [Firmware Bug]: ACPI(PEGP) defines _DOD but not _DOS > [ 2.861506] acpi device:2d: registered as cooling_device8 > [ 2.861646] ACPI: Video Device [PEGP] (multi-head: yes rom: no post: no) > [ 2.861679] input: Video Bus as > > /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2b/LNXVIDEO:00/input/input5 > [ 2.861724] [Firmware Bug]: Duplicate ACPI video bus devices for the same > VGA controller, please try module parameter "video.allow_duplicates=1"if the > current driver doesn't work. > [ 2.862467] acpi device:3c: registered as cooling_device9 > [ 2.862609] ACPI: Video Device [GFX0] (multi-head: yes rom: no post: no) > [ 2.862633] input: Video Bus as > /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:02/input/input6 > > Setting video.allow_duplicates=1 gives me a third acpi_video devices: The PEGP and VGA device have the same _ADR under the pci bridge named PEG0 in acpi table, don't know what BIOS wants to achieve here. Also, it's not clear why acpi device node PEGP's existence would be affected by win8 mode.
(In reply to comment #8) > (In reply to comment #7) > > (In reply to comment #3) > > > More findings: > > > > > > _BQC uses the CBLV variable as return value: > > > which is updated by the i915 driver after an ASLE interrupt. The AML has > a AINT > > > method which updates BCLP and triggers the interrupt, however, it's only > called > > > in the !Windows 8 case: > > > > That's interesting, how did you find this out? > > By just looking around :) I > - looked at the DSDT and saw it's using CBLV in _BQC > - grepped the kernel source for CBLV > - found drivers/gpu/drm/i915/intel_opregion.c > - checked it, found that the CBLV update (and the actual brightness update, > which is done in the same function - asle_set_backlight) is triggered by the > ASLE interrupt and the BCLP value > - grepped the DSDT for BCLP, found the AINT method which also sets ASLE > - found that it's only used in the !Windows 8 case > > I verified this by adding debug statements in intel_opregion.c, which proved > the expectations: In the !Windows 8 case, the ASLE interrupt is fired, CBLV > (and the actual backlight brightness) are updated and everything works as > intended. In the Windows 8 case, there's no ASLE interrupt, thus no CBLV > update > (which makes _BQC stuck) and no brightness update. Interesting finding, thanks for sharing. I suppose the intel IGD operation region spec can help here, but I'm not able to find it yet, though it should be publicly available. So the problem with acpi video driver is, it neither can set backlight level, nor can report backlight level in win8 mode. I hope you can find out the problem if you have the time, since you have the knowledge and access to the system, and I will help you any way I can. Looks like, most of the time, gpu driver's interface is more reliable than acpi's, and I'm thinking of some way to prefer gpu's interface, and have acpi video driver only handle hotkey notification. > > > > In the Windows 8 case, only the BRTS variable in the EC is written, thus > no > > > interrupt, thus no CBLV update, thus _BQC always stays at the same value. > Does > > > BRTS have some special meaning that I've missed? > > > > Perhaps only EC firmware writer knows that. > > I suppose on write to a variable in EC space, the EC firmware will do > something > > accordingly, but I'm not sure. > > OK. I was thinking from a spec perspective: Might it be that there's some new > mechanism for backlight control introduced with Windows 8 that the kernel > just > doesn't implement yet? I have no idea about this, sorry.
Created attachment 95961 [details] IGD opregion spec
(In reply to comment #11) > Interesting finding, thanks for sharing. I suppose the intel IGD operation > region spec can help here, but I'm not able to find it yet, though it should > be > publicly available. I've - after some heavy googling - found it ;) I've attached it. > So the problem with acpi video driver is, it neither can set backlight level, > nor can report backlight level in win8 mode. I hope you can find out the > problem if you have the time, since you have the knowledge and access to the > system, and I will help you any way I can. Maybe it doesn't look like it, but I actually lack the knowledge :-( I actually have no idea what the correct way to fix this problem is. > Looks like, most of the time, gpu driver's interface is more reliable than > acpi's, and I'm thinking of some way to prefer gpu's interface, and have acpi > video driver only handle hotkey notification. Yeah, maybe that's the solution. I guess exactly that is what's happening under Windows.
(In reply to comment #2) > Some more details: > > - In Windows 8 mode, _BCL reports 102 levels (100, 30, and 1-100). > - In that mode, I get 2 acpi_video devices instead of previously 1. > - Executing _BCM in either output device succeeds, but doesn't have any > visible > effect. _BQC always returns '100' afterwards, no matter what value was > written > via _BCM It looks like to me, Dell will provide some kind of platform driver, which will respond to EC memory space on write. And in win8 mode, _BCM will write the brightness level to BRTS which is in EC space; and since we don't have any special EC driver, that doesn't do anything; and in non-win8 mode, _BCM uses AINT, which uses the intel op-region method to update brightness level and worked. When you boot into win8, is there any EC driver listed in the device manager?
I think we can easily work around the _BQC problem(like the new quirk code here: http://marc.info/?l=linux-acpi&m=136529970126903&w=2), but for _BCM, it doesn't seem to be easy :-(
No, there's doesn't seem to be a EC driver installed. Device PNP0C09 ("Microsoft ACPI-Compliant Embedded Controller") is listed in the device manager with a driver created by Microsoft (driver date 6/21/06, version 6.2.9200.16384), but it looks like it's an INF 'driver' only, no .sys files involved.
Then my guess is, Dell do not want to support acpi interface for backlight control, they can do this by not doing anything in the EC firmware.
Hi Danny, I don't see anything we can do here to make _BCM work in win8 mode, so I'll close it as WILL_NOT_FIX, you will need the acpi_osi="!Windows 2012" kernel command line to work around this problem.
I came across a document on win8 brightness control, it has words like this: " In Windows 8, the primary mechanism by which a platform should expose its display brightness control functionality is the Windows Display Driver Model (WDDM) miniport Device Driver Interfaces (DDI). " So I think for win8 systems, they may not export correct _BCM/_BQC implementations since win8 does not need it. The document is here, in case you want to take a look: http://msdn.microsoft.com/en-US/library/windows/hardware/jj159305