Jump to content

Intel HD4600 banding/gradient/16-bit colors issue Y510p


intruder16
 Share

130 posts in this topic

Recommended Posts

The way I am thinking to solve this problem is to answer two questions:

  1. What happens to graphics (all the details) when the display is turned off
  2. What happens to graphics (all the details) when the display is turned on after being turned off

Knowing the answers will definitely give us a clue why the gradients happens after turning the display on again. Something during this process does not completely finish or finish using wrong set of parameters. I think we need to get to the root of the problem instead of try and error.

Link to comment
Share on other sites

@ahmed_ais:

 

Yep. That's what RehabMan suggested to me before. Something is going wrong while the display is initialising.

 

Nowadays i'm getting paranoid i think. I've using Windows only for the past month. I did a clean install of Windows again and installed Intel VGA drivers by Lenovo (which btw are from Oct 2013) and i think i've been seeing some gradients in movies, wallpapers etc xD. lol

Link to comment
Share on other sites

The way I am thinking to solve this problem is to answer two questions:

  1. What happens to graphics (all the details) when the display is turned off
  2. What happens to graphics (all the details) when the display is turned on after being turned off

Knowing the answers will definitely give us a clue why the gradients happens after turning the display on again. Something during this process does not completely finish or finish using wrong set of parameters. I think we need to get to the root of the problem instead of try and error.

 

On my laptop, a Lenovo G510, the gradient banding is there from boot to Finder-ready. So I'm not sure that the trigger is screen on/off (at least for me).

Link to comment
Share on other sites

@intruder16

 

I will agree with you regarding the gradients in Windows as I have seen this on wallpapers many times but I kept convincing myself that it is a problem with the image itself (silly). However, we do not see this issue on OS X (in full glory) until display is turned off then on again. So regardless of the situation on Windows we are able to get acceptable graphics on OS X before certain event is activated. This means there are no hardware faults and everything lies between the BIOS and the graphic driver. If Windows IGFX driver causes the same problem one way or another, then there is definitely a problem in BIOS or Windows driver is faulty as well. 

Link to comment
Share on other sites

@intruder16 , and all

 

Hey guys, I think I found something really important regarding the gradients issue which may change the way we think about the whole thing. Yesterday I was experimenting with Windows 7 USB that would not want to boot in UEFI mode. I had to change the boot mode in BIOS to Legacy Support then it was able to boot properly.
 
Today I tried to boot into OS X and was surprised to see the gradients issue (with restart malfunctioning too) from the start. I did not need to do anything to reproduce the issue it was there for me from the log screen. I returned to BIOS and reverted boot mode to UEFI then booted into OS X and the issue disappeared (until display goes off/on as we know). I tried this again to confirm and the issue is always there while boot mode is Legacy Support.
 
So there are some questions:

  • What is the relation between boot mode and the issue?
  • If we install all systems in non-EFI mode would the issue persist as well since the BIOS had to boot in Legacy Support? (this assumes either clover on MBR or chameleon)
  • Could this be a bug in Clover? as far as I know, Clover prepare the booting environment OS X is expecting and handles everything after POST until OS X boots up. So could there be something in Clover that is triggered (or not) as the display goes off results in OS X feels Legacy Support is there and hence the issue appears? this leeds us back to question 1 again.

On my laptop, a Lenovo G510, the gradient banding is there from boot to Finder-ready. So I'm not sure that the trigger is screen on/off (at least for me).


First you have a different model and I am not sure you are having the same exact issue described here. So please do not try any suggestion unless you know of the risks, if any. Second, what are you stating is in line with what I said above so are configuring your BIOS to Legacy Support?

Link to comment
Share on other sites

Update:

 

I would like to put an attention to a module in UEFI structure called Compatibility Support Module (CSM) which support booting from legacy systems. Setting BIOS boot mode to Legacy support means the CSM is either Auto or Enabled. On the other hand, there is a driver for Clover called CsmVideoDxe-64.efi that provides a wider set of resolutions than the ones present in UEFI CSM and I guess it forces booting in legacy mode if present in EFI/drivers regardless of BIOS setting. Upon booting with this driver, the Clover GUI will be invisible (not a problem for now) but I was able to boot into OS X nonetheless. Once OS X is booted, the same gradients/restart issue happened from the start and kept there without the need to set display off/on as described earlier.

Link to comment
Share on other sites

I read that Graphics Output Protocol (GOP) is part of GPU VBIOS that allow this GPU to work in UEFI. A GPU without GOP will not work in UEFI and the operating system will have to be installed and booted using in legacy mode. Reading about GOP on Wikipedia, I quote: 

 

EFI defines two types of services: boot services and runtime services. Boot services are only available while the firmware owns the platform (before the ExitBootServices call). Boot services include text and graphical consoles on various devices, and bus, block and file services. Runtime services are still accessible while the operating system is running; they include services such as date, time and NVRAM access.

In addition, the Graphics Output Protocol (GOP) provides limited runtime services support; see also Graphics features section below. The operating system is permitted to directly write to the framebuffer provided by GOP during runtime mode. However, the ability to change video modes is lost after transitioning to runtime services mode until the OS graphics driver is loaded.


I believe I can summarize the problem like this:

  • When OS X boots while Legacy Support mode is enabled, IGPU is initialized but its GOP is ignored. In this scenario, the issues are there all the time.
  • When OS X boots while UEFI mode is enabled instead, IGPU is initialized in UEFI mode with GOP used once on boot. Here the issues are not there until display goes off/on. Then the issues appears which may reflect that GOP is not utilized.

This rises two questions:

  • Why the issues happens in Legacy Support mode (without GOP)? is this a driver issue? because installing OS X Yosemite on Y510p in Legacy mode (on MBR for example) would render the graphics un-usable. I made a bootable USB with Clover (non-EFI) which required boot mode to be Legacy Support and the issue was there of course.
  • Is there a possibility to workaround GOP limitations so the video modes are not lost after display is set to off?
Link to comment
Share on other sites

I believe I can summarize the problem like this:

  • When Intel Mobile HD 4600 is initialized in Legacy Support mode (CSM is internally enabled) , the issues are there all the time.
  • When Intel Mobile HD 4600 is initialized in UEFI mode (CSM is internally disabled) , the issues are not there until display goes off/on. Then the issues appears which may reflect that IGPU is initialized in Legacy Suport mode (CSM is internally switched from disabled to enabled).
This rises two questions:
  • Why the issues happens in Legacy Support mode? 
  • Why the IGPU re-initialization after display off/on switches CSM on?

Difference is in IGPU initialization. During OS X startup, only a partial init is done as the drivers can depend on init by EFI firmware (eg. dependencies on what Apple knows their firmware does). During transition from sleep, full initialization must be done and so the problem appears on display wake/etc, wake from sleep, etc.

 

CSM enable/disable can affect how the IGPU is initialized by BIOS.

 

You should dump key registers using ACPIDebug.kext. You can also use ACPIPoller.kext to have the dump happen every second. It is a pure guessing game about which registers are significant. Refer to the IGPU PRM Linux/opensource docs for the Intel hardware: https://01.org/linuxgraphics/documentation/driver-documentation-prms

Link to comment
Share on other sites

 

I believe I can summarize the problem like this:

  • When Intel Mobile HD 4600 is initialized in Legacy Support mode (CSM is internally enabled) , the issues are there all the time.
  • When Intel Mobile HD 4600 is initialized in UEFI mode (CSM is internally disabled) , the issues are not there until display goes off/on. Then the issues appears which may reflect that IGPU is initialized in Legacy Suport mode (CSM is internally switched from disabled to enabled).

This rises two questions:

  1. Why the issues happens in Legacy Support mode? 
  2. Why the IGPU re-initialization after display off/on switches CSM on?

 

 

Wow. I thought I was having a slightly different issue from you guys as mine always showed the banding, but I just switched to UEFI Boot in the BIOS and now I have the same behavior, with banding not being present initially but occurring after the display goes on and off. Interesting.

Link to comment
Share on other sites

Difference is in IGPU initialization. During OS X startup, only a partial init is done as the drivers can depend on init by EFI firmware (eg. dependencies on what Apple knows their firmware does). During transition from sleep, full initialization must be done and so the problem appears on display wake/etc, wake from sleep, etc.

Thanks for your input, I appreciate it.

 

CSM enable/disable can affect how the IGPU is initialized by BIOS.

This rises a question. Assume that I want to only boot in Legacy mode for some reason. Then the IGPU is initialized differently and I have all the problems. But doesn't this mean the Fix for HD4600 mobile posted on the other forum is not enough? This is not an issue with Y510p only but also reported with Y410p and now G510 as well.

 

You should dump key registers using ACPIDebug.kext. You can also use ACPIPoller.kext to have the dump happen every second. It is a pure guessing game about which registers are significant. Refer to the IGPU PRM Linux/opensource docs for the Intel hardware: https://01.org/linuxgraphics/documentation/driver-documentation-prms

I hope we can do this (I was hoping to avoid it as it is a big mess).

 

Wow. I thought I was having a slightly different issue from you guys as mine always showed the banding, but I just switched to UEFI Boot in the BIOS and now I have the same behavior, with banding not being present initially but occurring after the display goes on and off. Interesting.

Welcome aboard dude!

Link to comment
Share on other sites

This rises a question. Assume that I want to only boot in Legacy mode for some reason. Then the IGPU is initialized differently and I have all the problems. But doesn't this mean the Fix for HD4600 mobile posted on the other forum is not enough? This is not an issue with Y510p only but also reported with Y410p and now G510 as well.

It varies by machine. My Lenovo u430 has less "boot glitch" when legacy is enabled than when UEFI only.

 

I hope we can do this (I was hoping to avoid it as it is a big mess).

There was an issue with Haswell brightness prior to display sleep (not sure if CSM was also significant or not).

 

I used ACPIDebug and ACPIPoller to determine this bit of code in the brightness patch for Haswell:

        // This 0xC value comes from looking what OS X initializes this\n
        // register to after display sleep (using ACPIDebug/ACPIPoller)\n
        Store(0xC0000000, LEVW)\n
Link to comment
Share on other sites

There was an issue with Haswell brightness prior to display sleep (not sure if CSM was also significant or not).

 

I used ACPIDebug and ACPIPoller to determine this bit of code in the brightness patch for Haswell:

        // This 0xC value comes from looking what OS X initializes this\n
        // register to after display sleep (using ACPIDebug/ACPIPoller)\n
        Store(0xC0000000, LEVW)\n

 

Thanks. I installed the kexts and made some tests for some variables using ACPIPoller. The major problem is to know the relation between the names in dump and those in SSDT.

Link to comment
Share on other sites

Thanks. I installed the kexts and made some tests for some variables using ACPIPoller. The major problem is to know the relation between the names in dump and those in SSDT.

 

@Rehabman

 

So from my understanding is that I have to:

  1. Know every register that change after driver re-initialisation by dumping Intel registers before and after then diff.
  2. Getting the address for each changed register by referring to Intel documentation which may be confusing since a single register called PIPE_DDI_FUNC_CTL_EDP have address between 6F400h-6F403h (or is it a start-end of a region?) 
  3. Assigning a name for the object/value at that address (in prober location at the ACPI table where IGPU is defined)
  4. Using ACPIDebug and ACPIPoller to check if the value of that name change and maybe change it back (although Intel restrict changing some fields for some/all registers while the register is functioning).

Am I on the right track?

Link to comment
Share on other sites

Thanks. I installed the kexts and made some tests for some variables using ACPIPoller. The major problem is to know the relation between the names in dump and those in SSDT.

Refer to the Intel PRM documentation for the offsets.

...

  • Know every register that change after driver re-initialisation by dumping Intel registers before and after then diff.

 

An educated guess based on reading the PRMs may be a better way to start.

 

 

  • Getting the address for each changed register by referring to Intel documentation which may be confusing since a single register called PIPE_DDI_FUNC_CTL_EDP have address between 6F400h-6F403h (or is it a start-end of a region?) 

 

It is a 32-bit register.

 

 

  • Assigning a name for the object/value at that address (in prober location at the ACPI table where IGPU is defined)

 

Refer to the Haswell brightness patch for clues.

 

 

  • Using ACPIDebug and ACPIPoller to check if the value of that name change and maybe change it back (although Intel restrict changing some fields for some/all registers while the register is functioning).

 

Yes. Compare register values when "working" and "not working"...

Link to comment
Share on other sites

An educated guess based on reading the PRMs may be a better way to start.

No doubt it is but when the documentation is 971 pages its hard to study it first. The time invested in reading and following up would be much more than iterating over the changed ones.

 

It is a 32-bit register.

Refer to the Haswell brightness patch for clues.

So something like this could work for the register PIPE_DDI_FUNC_CTL_EDP at address 6F400h-6F403h? (I'm not sure about OperationRegion and Field arguments and yes I'm reading ACPI spec for them)

OperationRegion (IGRG, SystemMemory, 0x6F400, 4)
Field (RMPC, AnyAcc, NoLock, Preserve)
{
   PEDP, 32,
}

IGRG is for Intel Graphics Register and PEDP is for PIPE_DDI_FUNC_CTL_EDP. Should the RegionSpace be SystemMemory or otherwise?

PS: the code for ACPIPoller is not included obviously but I know how to do it.

 

Yes. Compare register values when "working" and "not working"...

But is it allowable to change a value of register even if Intel states it is restricted?

Link to comment
Share on other sites

No doubt it is but when the documentation is 971 pages its hard to study it first. The time invested in reading and following up would be much more than iterating over the changed ones.

Yes, it took me more than a month to figure out Haswell backlight...

 

So something like this could work for the register PIPE_DDI_FUNC_CTL_EDP at address 6F400h-6F403h? (I'm not sure about OperationRegion and Field arguments and yes I'm reading ACPI spec for them)

OperationRegion (IGRG, SystemMemory, 0x6F400, 4)
Field (RMPC, AnyAcc, NoLock, Preserve)
{
   PEDP, 32,
}

 

I'm not reading the spec along with you, but if the spec states it is at a fixed address in system memory (I'm doubtful), then yes.

 

Most registers are relative to a BAR (base address register) in PCI_Config. If that is the case and 0x6F400 is a relative offset, see how you accomplish it in ACPI code by studying the Haswell brightness patch.

 

Note: I'm assuming you made a typo...correction:

OperationRegion (IGRG, SystemMemory, 0x6F400, 4)
Field (IGRG, AnyAcc, NoLock, Preserve)
{
   PEDP, 32,
}

But is it allowable to change a value of register even if Intel states it is restricted?

Not sure what you mean by "restricted." Some bits are documented as "Reserved" which means you shouldn't change them or rely on their value.

Link to comment
Share on other sites

I'm not reading the spec along with you, but if the spec states it is at a fixed address in system memory (I'm doubtful), then yes.

 

Most registers are relative to a BAR (base address register) in PCI_Config. If that is the case and 0x6F400 is a relative offset, see how you accomplish it in ACPI code by studying the Haswell brightness patch.

The spec does not "state" that but it does not state otherwise too. I will try to use the previous code assuming it is at a fixed address and poll its value. If it was the same as reported in the registers dump then it is at that address regardless of BAR1. Otherwise, I will follow the code for Haswell brightness patch. 

 

EDIT-1: I polled the value at the fixed location and it is different than what was expected so it is wrong and the register is at a relative offset to BAR1.

 

EDIT-2: I defined the correct region and polled the register. Its value is the same as the one returned from the dump and also changes as expected after display off/on. 

 

Note: I'm assuming you made a typo...

Yes it is, thanks.

 

Not sure what you mean by "restricted." Some bits are documented as "Reserved" which means you shouldn't change them or rely on their value.

I mean some fields within the register bits are restricted from being changed. For example lets look at all the registers of type PIPE_DDI_FUNC_CTL. The bits 22:20 are for the field Bits Per Color and beneath it written:

 

Restriction : This field must not be changed while the function is enabled.

Link to comment
Share on other sites

I tried to change the value of the register manually by setting the same value before display off/on. To be specific, the register PIPE_DDI_FUNC_CTL starts with the value of 0x82200002 and changes to 0x82000002 after driver re-initialization so I set the register to 0x82200002 in the poll (every second, for now). However, once the driver was re-initialized the display turned off immediately and I had to force shut down. I check the log after booting again and found the register value changed successfully but it appears something is wrong or this is not enough, I don't know for sure.

 

Here's my code so far: 

Device (POLL)
{
    Name (_HID, "GPU00000")

    OperationRegion (IGRG, SystemMemory, And(^BAR1, Not(0xF)), 0x6F404)
    Field (IGRG, AnyAcc, NoLock, Preserve)
    {
        Offset(0x6F400),
        PEDP, 32,
    }

    Method (PLIG, 0, Serialized)
    {
        \RMDT.P2("PIPE_DDI_FUNC_CTL_EDP: ", PEDP)
        Store(0x82200002, PEDP)
    }
}

and this is snapshot from the log that confirms the value change:

00:40:21 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:22 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:23 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:24 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82000002, } // driver re-initialized
00:40:25 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, } // register value restored
00:40:26 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:27 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
Just some clarification, the bits that change in this register on driver re-initialization are 22:20 which are for the field Bits Per Color as I wrote above. According to spec, the value 010b (0010b=2h) means 6 bits per color and 000b (0000b=0h) means 8 bits per color. 
Link to comment
Share on other sites

I mean some fields within the register bits are restricted from being changed. For example lets look at all the registers of type PIPE_DDI_FUNC_CTL. The bits 22:20 are for the field Bits Per Color and beneath it written:

Yes, it is pretty common for hardware registers to have these sorts of restrictions. Usually, init code must follow strict guidelines regarding order.

I tried to change the value of the register manually by setting the same value before display off/on. To be specific, the register PIPE_DDI_FUNC_CTL starts with the value of 0x82200002 and changes to 0x82000002 after driver re-initialization so I set the register to 0x82200002 in the poll (every second, for now). However, once the driver was re-initialized the display turned off immediately and I had to force shut down. I check the log after booting again and found the register value changed successfully but it appears something is wrong or this is not enough, I don't know for sure.

 

Here's my code so far: 

 

 

Device (POLL)
{
    Name (_HID, "GPU00000")

    OperationRegion (IGRG, SystemMemory, And(^BAR1, Not(0xF)), 0x6F404)
    Field (IGRG, AnyAcc, NoLock, Preserve)
    {
        Offset(0x6F400),
        PEDP, 32,
    }

    Method (PLIG, 0, Serialized)
    {
        \RMDT.P2("PIPE_DDI_FUNC_CTL_EDP: ", PEDP)
        Store(0x82200002, PEDP)
    }
}
and this is snapshot from the log that confirms the value change:

 

00:40:21 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:22 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:23 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:24 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82000002, } // driver re-initialized
00:40:25 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, } // register value restored
00:40:26 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }
00:40:27 kernel[0]: ACPIDebug: { "PIPE_DDI_FUNC_CTL_EDP: ", 0x82200002, }

 

Either not the right thing or something you can't change at that point.

Link to comment
Share on other sites

Either not the right thing ...

You mean not the correct register to tamper with? this is one of 7 registers that change after driver re-initialization as reported by AppleIntelInfo.kext.

 

... or something you can't change at that point.

You mean it can only be set/changed on driver initialisation at specific time when the order of assigning its value comes but not otherwise? if so, could this mean a driver patch is needed (the guys tried few patches in this thread and all failed)?

 

 

EDIT: or is the change is just an effect for some other cause and changing the effect back will not fix the cause but may make more problems?

Link to comment
Share on other sites

You mean not the correct register to tamper with?

That is a possibility.

 

You mean it can only be set/changed on driver initialisation at specific time when the order of assigning its value comes but not otherwise?

I don't know about this specific case, but it is not uncommon. You'll need to read the spec.

 

if so, could this mean a driver patch is needed (the guys tried few patches in this thread and all failed)?

Probably.

 

 

EDIT: or is the change is just an effect for some other cause and changing the effect back will not fix the cause but may make more problems?

It could be a red herring.

Link to comment
Share on other sites

That is a possibility.

 

 

I don't know about this specific case, but it is not uncommon. You'll need to read the spec.

 

 

Probably.

 

 

 

It could be a red herring.

 

Thanks for your thoughts and help. These are a lot of possibilities and probabilities  :). In addition, the PRM for Haswell are 15 volumes which makes one confused. Do you have a hint which one should be more relevant? The thing I am interested in is how -- from OS X prospective -- the graphic driver initializes from A to Z. The core of the driver may work the same way across all platforms with the same driver version but the most important in my opinion is how the OS work with that driver.

 

Instead of haunting down which register incorrectly initialized after driver re-initialization, I want to understand:

  1. The process of graphic driver re-initialization in OS X. How the driver is called to initialize and what are the parameters, if any, that are passed to the initialization process.
  2. What happens, in OS X, after the driver finishes his part in initialization. 
  3. Why CSM state makes such a big difference for graphic initialization
  4. If OS X is booted (and graphics partly initialized) with CSM-OFF, why OS X re-initialize graphics, when needed, as if CSM-ON (what triggers the switch?)
Link to comment
Share on other sites

 Share

×
×
  • Create New...