Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0217c42 authored by Eric Anholt's avatar Eric Anholt
Browse files

drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.



This is a sync of a fix I made in the old UMS code.  If the BIOS uses
the GMBUS and doesn't clear that setup, then our bit-banging I2C can
fail, leading to monitors not being detected.

Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent d09c23de
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -414,6 +414,13 @@
# define GPIO_DATA_VAL_IN		(1 << 12)
# define GPIO_DATA_VAL_IN		(1 << 12)
# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)


#define GMBUS0			0x5100
#define GMBUS1			0x5104
#define GMBUS2			0x5108
#define GMBUS3			0x510c
#define GMBUS4			0x5110
#define GMBUS5			0x5120

/*
/*
 * Clock control & power management
 * Clock control & power management
 */
 */
@@ -2166,6 +2173,13 @@
#define PCH_GPIOE               0xc5020
#define PCH_GPIOE               0xc5020
#define PCH_GPIOF               0xc5024
#define PCH_GPIOF               0xc5024


#define PCH_GMBUS0		0xc5100
#define PCH_GMBUS1		0xc5104
#define PCH_GMBUS2		0xc5108
#define PCH_GMBUS3		0xc510c
#define PCH_GMBUS4		0xc5110
#define PCH_GMBUS5		0xc5120

#define PCH_DPLL_A              0xc6014
#define PCH_DPLL_A              0xc6014
#define PCH_DPLL_B              0xc6018
#define PCH_DPLL_B              0xc6018


+4 −1
Original line number Original line Diff line number Diff line
@@ -27,7 +27,7 @@
#include "drmP.h"
#include "drmP.h"
#include "drm.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "intel_drv.h"


static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
{
@@ -816,6 +816,9 @@ int i915_restore_state(struct drm_device *dev)
	for (i = 0; i < 3; i++)
	for (i = 0; i < 3; i++)
		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);


	/* I2C state */
	intel_i2c_reset_gmbus(dev);

	return 0;
	return 0;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -162,6 +162,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter);
int intel_ddc_get_modes(struct intel_output *intel_output);
int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
void intel_i2c_reset_gmbus(struct drm_device *dev);

extern void intel_crt_init(struct drm_device *dev);
extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
+19 −0
Original line number Original line Diff line number Diff line
@@ -118,6 +118,23 @@ static void set_data(void *data, int state_high)
	udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
	udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
}
}


/* Clears the GMBUS setup.  Our driver doesn't make use of the GMBUS I2C
 * engine, but if the BIOS leaves it enabled, then that can break our use
 * of the bit-banging I2C interfaces.  This is notably the case with the
 * Mac Mini in EFI mode.
 */
void
intel_i2c_reset_gmbus(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (IS_IGDNG(dev)) {
		I915_WRITE(PCH_GMBUS0, 0);
	} else {
		I915_WRITE(GMBUS0, 0);
	}
}

/**
/**
 * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
 * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
 * @dev: DRM device
 * @dev: DRM device
@@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
	if(i2c_bit_add_bus(&chan->adapter))
	if(i2c_bit_add_bus(&chan->adapter))
		goto out_free;
		goto out_free;


	intel_i2c_reset_gmbus(dev);

	/* JJJ:  raise SCL and SDA? */
	/* JJJ:  raise SCL and SDA? */
	intel_i2c_quirk_set(dev, true);
	intel_i2c_quirk_set(dev, true);
	set_data(chan, 1);
	set_data(chan, 1);