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

Commit 0ba0e9e1 authored by Shaohua Li's avatar Shaohua Li Committed by Eric Anholt
Browse files

drm/i915: workaround IGD i2c bus issue in kernel side (v2)



In IGD, DPCUNIT_CLOCK_GATE_DISABLE bit should be set, otherwise i2c
access will be wrong.

v2: Disable CLOCK_GATE_DISABLE bit after bit bashing as suggested by Eric.

Signed-off-by: default avatarShaohua Li <shaohua.li@intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 13f4c435
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -526,6 +526,7 @@
#define   DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
#define D_STATE		0x6104
#define CG_2D_DIS	0x6200
#define DPCUNIT_CLOCK_GATE_DISABLE	(1 << 24)
#define CG_3D_DIS	0x6204

/*
+1 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
void intel_i2c_destroy(struct intel_i2c_chan *chan);
int intel_ddc_get_modes(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);
extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
+17 −0
Original line number Diff line number Diff line
@@ -34,6 +34,21 @@
#include "i915_drm.h"
#include "i915_drv.h"

void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	/* When using bit bashing for I2C, this bit needs to be set to 1 */
	if (!IS_IGD(dev))
		return;
	if (enable)
		I915_WRITE(CG_2D_DIS,
			I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
	else
		I915_WRITE(CG_2D_DIS,
			I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
}

/*
 * Intel GPIO access functions
 */
@@ -153,8 +168,10 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
		goto out_free;

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

	return chan;
+6 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/fb.h>
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drv.h"

/**
 * intel_ddc_probe
@@ -52,7 +53,10 @@ bool intel_ddc_probe(struct intel_output *intel_output)
		}
	};

	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
	ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);

	if (ret == 2)
		return true;

@@ -70,8 +74,10 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
	struct edid *edid;
	int ret = 0;

	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
	edid = drm_get_edid(&intel_output->base,
			    &intel_output->ddc_bus->adapter);
	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
	if (edid) {
		drm_mode_connector_update_edid_property(&intel_output->base,
							edid);