Jump to content

Y510p (Intel HD4600) IGPU driver initialisation/re-initialisation problem


ahmed_ais
 Share

7 posts in this topic

Recommended Posts

Hi all. I have a Lenovo Ideapad Y510p that runs with Intel HD4600. I found there is a big problem with IGPU driver initialisation/re-initialisation and was hoping some of you who have experience with drivers and graphic can help me out.
 
Problem description 

If I started the system with Legacy support disabled in BIOS (i.e. UEFI-Only / CSM-OFF), the whole system boots fine. Whenever anything causes display off/on (like change resolution, connect external display, set display to sleep, or set system to sleep) then On while using OS X, something big change with graphics. At this event there is no symptoms visible inside OS X but once I choose to reboot display goes off (part of any reboot process) but never wakes. Therefore, Lenovo logo is not visible, so is Clover bootloader (while functioning), the same is for any OS I choose to boot to (blindly). I was able to force the display to wake again by re-initialising GFX once I am inside operating system using this trick:

  • For OS X, I turn the display Off then On (Ctrl+Shift+Eject) ... or set the system to sleep then wake it
  • For Windows I set the system to sleep then wake it.

The next figure shows the process and I hope it make the problem clearer. I want to note that shutdown is not affected since UEFI will initialise the graphics correctly on cold boot. 
Screen_Shot_2015_06_15_at_13_03_31.png
  
Now if I started the system with Legacy support enabled in BIOS (i.e. UEFI + Legacy / CSM-ON), the whole system boots fine too. But there is no need to turn display OFF then ON to test the change with graphics while in OS X. Once I choose to reboot display goes off but never wakes and all the other consequences happens as with the other case.
Screen_Shot_2015_06_15_at_13_03_50.png
 
Other things I tried that replicates the same issue:

  • Booting the system (regardless of CSM mode) while having CsmVideoDxe-64.efi installed with Clover. The system boots with blinking cursor and no GUI for clover but still functioning and I am able to boot OS X blindly. Once I boot OS X I make the trick above to re-initialise GFX then display is back On but reboot is flawed.
  • Booting the system (regardless of CSM mode) while having PatchVBios=true set in config.plist. The system boots with no display no GUI for clover of course but still functioning and I am able to boot OS X blindly. Once I boot OS X I again make the trick above to re-initialise GFX then display is back On but reboot is flawed.

I understand that both CsmVideoDxe-64.efi driver and PatchVBios setting have their own purpose but it is still interesting to see how they can trigger the problem by their own.
 
Experimenting with Intel Registers:
 
 The first thing I tried while investigating is to dump and analyse Intel GPU Registers. I dumped the registers using AppleIntelInfo in four situations:

  • While booting in UEFI-Only / CSM-OFF mode (before IGPU is re-initialised)
  • While booting in UEFI-Only / CSM-OFF mode (after IGPU is re-initialised)
  • While booting in UEFI+Legacy / CSM-ON mode (before IGPU is re-initialised)
  • While booting in UEFI+Legacy / CSM-ON mode (after IGPU is re-initialised)

And the following results are what I found:

  • These registers will always change (even on different boots with the same configuration) so I guess they are not relevant:
        AICPUPMI: InitialTSC
        AICPUPMI: IA32_MPERF
        AICPUPMI: IA32_APERF
        AICPUPMI: IA32_THERM_STATUS
        AICPUPMI: MSR_PKG_ENERGY_STATUS
        AICPUPMI: MSR_PP0_ENERGY_STATUS
        AICPUPMI: MSR_PP1_ENERGY_STATUS
        AICPUPMI: MSR_PKG_C2_RESIDENCY
        AICPUPMI: MSR_PKG_C3_RESIDENCY
        AICPUPMI: IA32_TSC_DEADLINE
     
        DSPASURF
        RC6_RESIDENCY_TIME
  • UEFI-Only-Before vs. UEFI-Only-After, the following additional registers will change:
       DP_TP_CTL_A
       DDI_BUF_CTL_A
  • UEFI+Legacy-Before vs. UEFI+Legacy-After, no additional registers changes!
  • UEFI-Only-Before vs UEFI+Legacy-Before, the following additional registers will change:
       DP_TP_CTL_A
       DDI_BUF_CTL_A
       BLC_PWM_CPU_CTL2
       BLC_PWM_CPU_CTL
  • UEFI-Only-Before vs UEFI+Legacy-After, the following additional registers will change:
       DP_TP_CTL_A
       DDI_BUF_CTL_A
       BLC_PWM_CPU_CTL2
       BLC_PWM_CPU_CTL
  • UEFI-Only-After vs UEFI+Legacy-Before, the following additional registers will change:
       BLC_PWM_CPU_CTL2
       BLC_PWM_CPU_CTL
  • UEFI-Only-After vs UEFI+Legacy-After, the following additional registers will change:
       BLC_PWM_CPU_CTL2
       BLC_PWM_CPU_CTL

Before this becomes messy, I want to note that the only case that IGPU are fine is UEFI-Only-Before. This means the question is why the other cases have differences/changes in registers. we have four registers to look at:

  • DP_TP_CTL_A
  • DDI_BUF_CTL_A
  • BLC_PWM_CPU_CTL2
  • BLC_PWM_CPU_CTL

Let's start with the last two of them BLC_PWM_CPU_CTL2 and BLC_PWM_CPU_CTL. Their values are different based on the boot mode. That is, these two registers will have a specific values if we boot in UEFI-only mode and other values if we boot in Legacy support mode but in both cases the registers values does not change on IGPU re-initialisation. Therefore, I believe they are not much relevant but they serve as evidence that OS X initialise IGPU differently depending on CSM mode in BIOS. 
 
The other two registers are DP_TP_CTL_A and DDI_BUF_CTL_A. These two registers change once IGPU is re-initialised if we boot in UEFI-Only mode and the change in these registers are:

  • DP_TP_CTL_A     : 0x80040300 -> 0x80040340
  • DDI_BUF_CTL_A : 0x80000003 -> 0x8000001

If we boot in Legacy support mode, however, we find that these registers are already set to the wrong values right from the start. That is on cold boot while Legacy support enabled in BIOS, DP_TP_CTL_A = 0x80040340 and DDI_BUF_CTL_A = 0x80000013. In this scenario, no matter how many times IGPU is further re-initialised these two registers will not change anymore.
 
So the conclusions here is:

  • OS X initialise IGPU differently depending on whether BIOS enables CSM or not. This is visible through the values of the two registers BLC_PWM_CPU_CTL2 and BLC_PWM_CPU_CTL.
  • Whenever DP_TP_CTL_A = 0x80040340 and DDI_BUF_CTL_A = 0x80000013, the system will restart with display off and reproduce the issue presented above. So I would name the initialisation that led to this an incorrect initialisation.
  • OS X initialise IGPU incorrectly while in CSM-ON mode with wrong values assigned for DP_TP_CTL_A and DDI_BUF_CTL_A registers.
  • If OS X booted in CSM-OFF mode and IGPU is re-initialised, the values of the  two registers DP_TP_CTL_A and DDI_BUF_CTL_A will change to match their values in CSM-ON case (which are wrong according to 3).
  • We need to find the reason why the two registers DP_TP_CTL_A and DDI_BUF_CTL_A are initialised incorrectly for CSM-On mode (this will affect IGPU re-initialisation while on CSM-OFF mode).
Let’s start with DP_TP_CTL_A which have a value that corresponds ‘good-mode’ is 0x80040300. This value changes on ‘bad-mode’ to 0x80040340 which means a single change to the bit number 6 for this register. This bit changes from 0 to 1 and according to Intel PRM it is defined as:
 
Alternate SR Enable “This bit enables the DisplayPort Alternate Scrambler Reset, intended for use only with embedded DisplayPort receivers”.
 
Moreover, the PRM states that value 0 for this bit means disabled while 1 for enabled. So on IGPU re-initialisation, the IGPU driver accidentally enable DisplayPort Alternate Scrambler Reset which should not happen.
 
Now with the other register DDI_BUF_CTL_A that have a ‘good-mode’ value of 0x80000003. This value changes on ‘bad-mode’ to 0x80000013 which means a single change to the bit number 4 for this register. This bit changes from 0 to 1 and according to Intel PRM it is defined as:
 
DDIA Lane Capability Control “This bit selects how lanes are shared between DDI A and DDI E. Restriction : This field must be programmed at system boot based on board configuration and may not be changed afterwards”.
 
Moreover, the PRM states that value 0 for this bit means ”DDI A supports 2 lanes and DDI E supports 2 lanes” while 1 means “DDI A supports 4 lanes and DDI E is not used”. So on IGPU re-initialisation, the IGPU driver accidentally switch DDI A support to 4 lanes and disables DDI E which, again, should not happen.
 
I also read from the PRM that the questionable bits in both registers should not be changed manually. I can deliberately change the values via ACPI but I tried this before on other IGPU register and it didn't work (the register did changed but display went out). Therefor, I was wondering if there should be something to fix the registers at boot-time (fixing the cause of course). We had a problem before with colour gradients that occur as well after IGPU re-initialisation (or if boot in CSM-ON mode) and resulted in an incorrect change to the register PIPE_DDI_FUNC_CTL_EDP. It was found that using a custom EDID was enough to fix the visible symptoms and also prevent the infected registers from change incorrectly.
 
So this is what I found so far ... I will keep searching and trying things but was hoping to get any help. I am attaching a copy of Intel registers dump for all four cases discussed above for reference.
 
Thanks in advance.

Intel Registers Dump.zip

  • Like 2
Link to comment
Share on other sites

Ever give El Capitan a thought pal ? HD5500 and HD6000 from Broadwell laptops/NUCs suffer from this as well on Yosemite, but fixed in El Capitan

 

That's really good to hear ... I'm gonna give El Capitan a try and report back. Thanks!

  • Like 1
Link to comment
Share on other sites

Thanks. I followed the link, and other topics where lisai's posted to track his problem. I believe I got an idea of what they had with HD5500 although their topic is not very informative. So they had a kernel panic related to IGPU that needed changing DVMT and using specific ig-platform-id which resulted in working system with two issues. The first is grappled display that is fixable by changing resolution back and fourth or enable CSM in BIOS. And the second issue is random IGPU hang which is fixed in El Capitan OOB.

 

Their solution for first issue to change resolution is just a mean to re-initialise IGPU in CSM-On mode = booting OS X in CSM-On mode set in BIOS. But they did not report whether after doing this workaround would they be able to restart with display on?  Also from what I understood that El Capitan only fixed the second issue (which was bad) so I cannot correlate El Capitan with their first issue (or mine as well).

Link to comment
Share on other sites

Just some updates regarding DDI_BUF_CTL_A register. I found a patch introduced for Linux kernel v3.10.6 that is very related:
 

commit 6b9f3486bb756d0aa6c00d7f745c8ca65ff35f07
Author: Stéphane Marchesin <marcheu@chromium.org>
Date: Fri Jul 12 13:54:41 2013 -0700
 

drm/i915: Preserve the DDI_A_4_LANES bit from the bios

commit bcf53de4e60d9000b82f541d654529e2902a4c2c upstream.

Otherwise the DDI_A_4_LANES bit gets lost and we can't use > 2 lanes
on eDP. This fixes eDP on hsw with > 2 lanes.


Also s/port_reversal/saved_port_bits/ since the current name is
confusing.

Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Zhouping Liu <zliu@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 


And this is the code I found for this patch:

Signed-off-by: Stéphane Marchesin <marc...@chromium.org>
	---
	 drivers/gpu/drm/i915/intel_ddi.c | 10 ++++++----
	 drivers/gpu/drm/i915/intel_drv.h |  2 +-
	 2 files changed, 7 insertions(+), 5 deletions(-)

	diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
	index 324211a..b042ee5 100644
	--- a/drivers/gpu/drm/i915/intel_ddi.c
	+++ b/drivers/gpu/drm/i915/intel_ddi.c
	@@ -301,7 +301,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
			struct intel_digital_port *intel_dig_port =
				enc_to_dig_port(encoder);

	-		intel_dp->DP = intel_dig_port->port_reversal |
	+		intel_dp->DP = intel_dig_port->saved_port_bits |
					   DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
			intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);

	@@ -1109,7 +1109,8 @@ static void intel_enable_ddi(struct intel_encoder
	*intel_encoder)
			 * enabling the port.
			 */
			I915_WRITE(DDI_BUF_CTL(port),
	-			   intel_dig_port->port_reversal | DDI_BUF_CTL_ENABLE);
	+			   intel_dig_port->saved_port_bits |
	+			   DDI_BUF_CTL_ENABLE);
		} else if (type == INTEL_OUTPUT_EDP) {
			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);

	@@ -1347,8 +1348,9 @@ void intel_ddi_init(struct drm_device *dev, enum port
	port)
		intel_encoder->get_config = intel_ddi_get_config;

		intel_dig_port->port = port;
	-	intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
	-					DDI_BUF_PORT_REVERSAL;
	+	intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
	+					  (DDI_BUF_PORT_REVERSAL |
	+					   DDI_A_4_LANES);
		intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);

		intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
	diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
	index c8c9b6f..b7d6e09 100644
	--- a/drivers/gpu/drm/i915/intel_drv.h
	+++ b/drivers/gpu/drm/i915/intel_drv.h
	@@ -504,7 +504,7 @@ struct intel_dp {
	 struct intel_digital_port {
		struct intel_encoder base;
		enum port port;
	-	u32 port_reversal;
	+	u32 saved_port_bits;
		struct intel_dp dp;
		struct intel_hdmi hdmi;
	 };
	-- 
	1.8.3

I believe it is a graphic driver patch so it should correspond to a patch to one of the graphic-related kexts but I still have no idea which one and how to do that.

Link to comment
Share on other sites

 Share

×
×
  • Create New...