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

Commit 269b62db authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

Daniel writes:

" First -next pull for 3.7. Highlights:
- hsw hdmi improvements (Paulo)
- ips/rps locking rework and cleanups
- rc6 on ilk by default again
- hw context&dp&dpff support for hsw (Ben)
- GET_PARAM_HAS_SEMAPHORES (Chris)
- gen6+ pipe_control improvements (Chris)
- set_cacheing ioctl and assorted support code (Chris)
- cleanups around the busy/idle/pm code (Chris&me)
- flushing_list removal, hopefully for good (Chris)
- read_reg ioctl (Ben)
- support the ns2501 dvo (Thomas Richter)
- avoid the costly gen6+ "missed IRQ" workaround where we don't need a
  race-free seqno readback (Chris)
- various bits&pieces, mostly early patches from the modeset rework branch"

* 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel: (54 commits)
  drm/i915: don't grab dev->struct_mutex for userspace forcewak
  drm/i915: try harder to find WR PLL clock settings
  drm/i915: use the correct encoder type when comparing
  drm/i915: Lazily apply the SNB+ seqno w/a
  drm/i915: enable rc6 on ilk again
  drm/i915: fix up ilk drps/ips locking
  drm/i915: DE_PCU_EVENT irq is ilk-only
  drm/i915: kill dev_priv->mchdev_lock
  drm/i915: move all rps state into dev_priv->rps
  drm/i915: use mutex_lock_interruptible for debugfs files
  drm/i915: fixup up debugfs rps state handling
  drm/i915: properly guard ilk ips state
  drm/i915: add parentheses around PIXCLK_GATE definitions
  drm/i915: reindent Haswell register definitions
  drm/i915: completely reset the value of DDI_FUNC_CTL
  drm/i915: correctly set the DDI_FUNC_CTL bpc field
  drm/i915: set the DDI sync polarity bits
  drm/i915: fix pipe DDI mode select
  drm/i915: dump the device info
  drm/i915: fixup desired rps frequency computation
  ...
parents d9875690 a22ddff8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
	  dvo_ivch.o \
	  dvo_tfp410.o \
	  dvo_sil164.o \
	  dvo_ns2501.o \
	  i915_gem_dmabuf.o

i915-$(CONFIG_COMPAT)   += i915_ioc32.o
+1 −0
Original line number Diff line number Diff line
@@ -140,5 +140,6 @@ extern struct intel_dvo_dev_ops ch7xxx_ops;
extern struct intel_dvo_dev_ops ivch_ops;
extern struct intel_dvo_dev_ops tfp410_ops;
extern struct intel_dvo_dev_ops ch7017_ops;
extern struct intel_dvo_dev_ops ns2501_ops;

#endif /* _INTEL_DVO_H */
+582 −0
Original line number Diff line number Diff line
/*
 *
 * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
 *
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include "dvo.h"
#include "i915_reg.h"
#include "i915_drv.h"

#define NS2501_VID 0x1305
#define NS2501_DID 0x6726

#define NS2501_VID_LO 0x00
#define NS2501_VID_HI 0x01
#define NS2501_DID_LO 0x02
#define NS2501_DID_HI 0x03
#define NS2501_REV 0x04
#define NS2501_RSVD 0x05
#define NS2501_FREQ_LO 0x06
#define NS2501_FREQ_HI 0x07

#define NS2501_REG8 0x08
#define NS2501_8_VEN (1<<5)
#define NS2501_8_HEN (1<<4)
#define NS2501_8_DSEL (1<<3)
#define NS2501_8_BPAS (1<<2)
#define NS2501_8_RSVD (1<<1)
#define NS2501_8_PD (1<<0)

#define NS2501_REG9 0x09
#define NS2501_9_VLOW (1<<7)
#define NS2501_9_MSEL_MASK (0x7<<4)
#define NS2501_9_TSEL (1<<3)
#define NS2501_9_RSEN (1<<2)
#define NS2501_9_RSVD (1<<1)
#define NS2501_9_MDI (1<<0)

#define NS2501_REGC 0x0c

struct ns2501_priv {
	//I2CDevRec d;
	bool quiet;
	int reg_8_shadow;
	int reg_8_set;
	// Shadow registers for i915
	int dvoc;
	int pll_a;
	int srcdim;
	int fw_blc;
};

#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))

/*
 * Include the PLL launcher prototype
 */
extern void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe);

/*
 * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
 * laptops does not react on the i2c bus unless
 * both the PLL is running and the display is configured in its native
 * resolution.
 * This function forces the DVO on, and stores the registers it touches.
 * Afterwards, registers are restored to regular values.
 *
 * This is pretty much a hack, though it works.
 * Without that, ns2501_readb and ns2501_writeb fail
 * when switching the resolution.
 */

static void enable_dvo(struct intel_dvo_device *dvo)
{
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
	struct i2c_adapter *adapter = dvo->i2c_bus;
	struct intel_gmbus *bus = container_of(adapter,
					       struct intel_gmbus,
					       adapter);
	struct drm_i915_private *dev_priv = bus->dev_priv;

	DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);

	ns->dvoc = I915_READ(DVO_C);
	ns->pll_a = I915_READ(_DPLL_A);
	ns->srcdim = I915_READ(DVOC_SRCDIM);
	ns->fw_blc = I915_READ(FW_BLC);

	I915_WRITE(DVOC, 0x10004084);
	I915_WRITE(_DPLL_A, 0xd0820000);
	I915_WRITE(DVOC_SRCDIM, 0x400300);	// 1024x768
	I915_WRITE(FW_BLC, 0x1080304);

	intel_enable_pll(dev_priv, 0);

	I915_WRITE(DVOC, 0x90004084);
}

/*
 * Restore the I915 registers modified by the above
 * trigger function.
 */
static void restore_dvo(struct intel_dvo_device *dvo)
{
	struct i2c_adapter *adapter = dvo->i2c_bus;
	struct intel_gmbus *bus = container_of(adapter,
					       struct intel_gmbus,
					       adapter);
	struct drm_i915_private *dev_priv = bus->dev_priv;
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);

	I915_WRITE(DVOC, ns->dvoc);
	I915_WRITE(_DPLL_A, ns->pll_a);
	I915_WRITE(DVOC_SRCDIM, ns->srcdim);
	I915_WRITE(FW_BLC, ns->fw_blc);
}

/*
** Read a register from the ns2501.
** Returns true if successful, false otherwise.
** If it returns false, it might be wise to enable the
** DVO with the above function.
*/
static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
{
	struct ns2501_priv *ns = dvo->dev_priv;
	struct i2c_adapter *adapter = dvo->i2c_bus;
	u8 out_buf[2];
	u8 in_buf[2];

	struct i2c_msg msgs[] = {
		{
		 .addr = dvo->slave_addr,
		 .flags = 0,
		 .len = 1,
		 .buf = out_buf,
		 },
		{
		 .addr = dvo->slave_addr,
		 .flags = I2C_M_RD,
		 .len = 1,
		 .buf = in_buf,
		 }
	};

	out_buf[0] = addr;
	out_buf[1] = 0;

	if (i2c_transfer(adapter, msgs, 2) == 2) {
		*ch = in_buf[0];
		return true;
	};

	if (!ns->quiet) {
		DRM_DEBUG_KMS
		    ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
		     adapter->name, dvo->slave_addr);
	}

	return false;
}

/*
** Write a register to the ns2501.
** Returns true if successful, false otherwise.
** If it returns false, it might be wise to enable the
** DVO with the above function.
*/
static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
	struct ns2501_priv *ns = dvo->dev_priv;
	struct i2c_adapter *adapter = dvo->i2c_bus;
	uint8_t out_buf[2];

	struct i2c_msg msg = {
		.addr = dvo->slave_addr,
		.flags = 0,
		.len = 2,
		.buf = out_buf,
	};

	out_buf[0] = addr;
	out_buf[1] = ch;

	if (i2c_transfer(adapter, &msg, 1) == 1) {
		return true;
	}

	if (!ns->quiet) {
		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
			      addr, adapter->name, dvo->slave_addr);
	}

	return false;
}

/* National Semiconductor 2501 driver for chip on i2c bus
 * scan for the chip on the bus.
 * Hope the VBIOS initialized the PLL correctly so we can
 * talk to it. If not, it will not be seen and not detected.
 * Bummer!
 */
static bool ns2501_init(struct intel_dvo_device *dvo,
			struct i2c_adapter *adapter)
{
	/* this will detect the NS2501 chip on the specified i2c bus */
	struct ns2501_priv *ns;
	unsigned char ch;

	ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
	if (ns == NULL)
		return false;

	dvo->i2c_bus = adapter;
	dvo->dev_priv = ns;
	ns->quiet = true;

	if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
		goto out;

	if (ch != (NS2501_VID & 0xff)) {
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
			      ch, adapter->name, dvo->slave_addr);
		goto out;
	}

	if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
		goto out;

	if (ch != (NS2501_DID & 0xff)) {
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
			      ch, adapter->name, dvo->slave_addr);
		goto out;
	}
	ns->quiet = false;
	ns->reg_8_set = 0;
	ns->reg_8_shadow =
	    NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | NS2501_8_HEN;

	DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
	return true;

out:
	kfree(ns);
	return false;
}

static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
{
	/*
	 * This is a Laptop display, it doesn't have hotplugging.
	 * Even if not, the detection bit of the 2501 is unreliable as
	 * it only works for some display types.
	 * It is even more unreliable as the PLL must be active for
	 * allowing reading from the chiop.
	 */
	return connector_status_connected;
}

static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
					      struct drm_display_mode *mode)
{
	DRM_DEBUG_KMS
	    ("%s: is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
	     mode->vtotal);

	/*
	 * Currently, these are all the modes I have data from.
	 * More might exist. Unclear how to find the native resolution
	 * of the panel in here so we could always accept it
	 * by disabling the scaler.
	 */
	if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
	    (mode->hdisplay == 640 && mode->vdisplay == 480) ||
	    (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
		return MODE_OK;
	} else {
		return MODE_ONE_SIZE;	/* Is this a reasonable error? */
	}
}

static void ns2501_mode_set(struct intel_dvo_device *dvo,
			    struct drm_display_mode *mode,
			    struct drm_display_mode *adjusted_mode)
{
	bool ok;
	bool restore = false;
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);

	DRM_DEBUG_KMS
	    ("%s: set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
	     mode->vtotal);

	/*
	 * Where do I find the native resolution for which scaling is not required???
	 *
	 * First trigger the DVO on as otherwise the chip does not appear on the i2c
	 * bus.
	 */
	do {
		ok = true;

		if (mode->hdisplay == 800 && mode->vdisplay == 600) {
			/* mode 277 */
			ns->reg_8_shadow &= ~NS2501_8_BPAS;
			DRM_DEBUG_KMS("%s: switching to 800x600\n",
				      __FUNCTION__);

			/*
			 * No, I do not know where this data comes from.
			 * It is just what the video bios left in the DVO, so
			 * I'm just copying it here over.
			 * This also means that I cannot support any other modes
			 * except the ones supported by the bios.
			 */
			ok &= ns2501_writeb(dvo, 0x11, 0xc8);	// 0xc7 also works.
			ok &= ns2501_writeb(dvo, 0x1b, 0x19);
			ok &= ns2501_writeb(dvo, 0x1c, 0x62);	// VBIOS left 0x64 here, but 0x62 works nicer
			ok &= ns2501_writeb(dvo, 0x1d, 0x02);

			ok &= ns2501_writeb(dvo, 0x34, 0x03);
			ok &= ns2501_writeb(dvo, 0x35, 0xff);

			ok &= ns2501_writeb(dvo, 0x80, 0x27);
			ok &= ns2501_writeb(dvo, 0x81, 0x03);
			ok &= ns2501_writeb(dvo, 0x82, 0x41);
			ok &= ns2501_writeb(dvo, 0x83, 0x05);

			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
			ok &= ns2501_writeb(dvo, 0x8e, 0x04);
			ok &= ns2501_writeb(dvo, 0x8f, 0x00);

			ok &= ns2501_writeb(dvo, 0x90, 0xfe);	/* vertical. VBIOS left 0xff here, but 0xfe works better */
			ok &= ns2501_writeb(dvo, 0x91, 0x07);
			ok &= ns2501_writeb(dvo, 0x94, 0x00);
			ok &= ns2501_writeb(dvo, 0x95, 0x00);

			ok &= ns2501_writeb(dvo, 0x96, 0x00);

			ok &= ns2501_writeb(dvo, 0x99, 0x00);
			ok &= ns2501_writeb(dvo, 0x9a, 0x88);

			ok &= ns2501_writeb(dvo, 0x9c, 0x23);	/* Looks like first and last line of the image. */
			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
			ok &= ns2501_writeb(dvo, 0x9f, 0x03);

			ok &= ns2501_writeb(dvo, 0xa4, 0x80);

			ok &= ns2501_writeb(dvo, 0xb6, 0x00);

			ok &= ns2501_writeb(dvo, 0xb9, 0xc8);	/* horizontal? */
			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */

			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
			ok &= ns2501_writeb(dvo, 0xc1, 0xd7);

			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
			ok &= ns2501_writeb(dvo, 0xc3, 0xf8);

			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
			ok &= ns2501_writeb(dvo, 0xc5, 0x1a);

			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
			ok &= ns2501_writeb(dvo, 0xc7, 0x73);
			ok &= ns2501_writeb(dvo, 0xc8, 0x02);

		} else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
			/* mode 274 */
			DRM_DEBUG_KMS("%s: switching to 640x480\n",
				      __FUNCTION__);
			/*
			 * No, I do not know where this data comes from.
			 * It is just what the video bios left in the DVO, so
			 * I'm just copying it here over.
			 * This also means that I cannot support any other modes
			 * except the ones supported by the bios.
			 */
			ns->reg_8_shadow &= ~NS2501_8_BPAS;

			ok &= ns2501_writeb(dvo, 0x11, 0xa0);
			ok &= ns2501_writeb(dvo, 0x1b, 0x11);
			ok &= ns2501_writeb(dvo, 0x1c, 0x54);
			ok &= ns2501_writeb(dvo, 0x1d, 0x03);

			ok &= ns2501_writeb(dvo, 0x34, 0x03);
			ok &= ns2501_writeb(dvo, 0x35, 0xff);

			ok &= ns2501_writeb(dvo, 0x80, 0xff);
			ok &= ns2501_writeb(dvo, 0x81, 0x07);
			ok &= ns2501_writeb(dvo, 0x82, 0x3d);
			ok &= ns2501_writeb(dvo, 0x83, 0x05);

			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
			ok &= ns2501_writeb(dvo, 0x8e, 0x10);
			ok &= ns2501_writeb(dvo, 0x8f, 0x00);

			ok &= ns2501_writeb(dvo, 0x90, 0xff);	/* vertical */
			ok &= ns2501_writeb(dvo, 0x91, 0x07);
			ok &= ns2501_writeb(dvo, 0x94, 0x00);
			ok &= ns2501_writeb(dvo, 0x95, 0x00);

			ok &= ns2501_writeb(dvo, 0x96, 0x05);

			ok &= ns2501_writeb(dvo, 0x99, 0x00);
			ok &= ns2501_writeb(dvo, 0x9a, 0x88);

			ok &= ns2501_writeb(dvo, 0x9c, 0x24);
			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
			ok &= ns2501_writeb(dvo, 0x9f, 0x03);

			ok &= ns2501_writeb(dvo, 0xa4, 0x84);

			ok &= ns2501_writeb(dvo, 0xb6, 0x09);

			ok &= ns2501_writeb(dvo, 0xb9, 0xa0);	/* horizontal? */
			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */

			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
			ok &= ns2501_writeb(dvo, 0xc1, 0x90);

			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
			ok &= ns2501_writeb(dvo, 0xc3, 0x0f);

			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
			ok &= ns2501_writeb(dvo, 0xc5, 0x16);

			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
			ok &= ns2501_writeb(dvo, 0xc7, 0x02);
			ok &= ns2501_writeb(dvo, 0xc8, 0x02);

		} else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
			/* mode 280 */
			DRM_DEBUG_KMS("%s: switching to 1024x768\n",
				      __FUNCTION__);
			/*
			 * This might or might not work, actually. I'm silently
			 * assuming here that the native panel resolution is
			 * 1024x768. If not, then this leaves the scaler disabled
			 * generating a picture that is likely not the expected.
			 *
			 * Problem is that I do not know where to take the panel
			 * dimensions from.
			 *
			 * Enable the bypass, scaling not required.
			 *
			 * The scaler registers are irrelevant here....
			 *
			 */
			ns->reg_8_shadow |= NS2501_8_BPAS;
			ok &= ns2501_writeb(dvo, 0x37, 0x44);
		} else {
			/*
			 * Data not known. Bummer!
			 * Hopefully, the code should not go here
			 * as mode_OK delivered no other modes.
			 */
			ns->reg_8_shadow |= NS2501_8_BPAS;
		}
		ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);

		if (!ok) {
			if (restore)
				restore_dvo(dvo);
			enable_dvo(dvo);
			restore = true;
		}
	} while (!ok);
	/*
	 * Restore the old i915 registers before
	 * forcing the ns2501 on.
	 */
	if (restore)
		restore_dvo(dvo);
}

/* set the NS2501 power state */
static void ns2501_dpms(struct intel_dvo_device *dvo, int mode)
{
	bool ok;
	bool restore = false;
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
	unsigned char ch;

	DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to %d\n",
		      __FUNCTION__, mode);

	ch = ns->reg_8_shadow;

	if (mode == DRM_MODE_DPMS_ON)
		ch |= NS2501_8_PD;
	else
		ch &= ~NS2501_8_PD;

	if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
		ns->reg_8_set = 1;
		ns->reg_8_shadow = ch;

		do {
			ok = true;
			ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
			ok &=
			    ns2501_writeb(dvo, 0x34,
					  (mode ==
					   DRM_MODE_DPMS_ON) ? (0x03) : (0x00));
			ok &=
			    ns2501_writeb(dvo, 0x35,
					  (mode ==
					   DRM_MODE_DPMS_ON) ? (0xff) : (0x00));
			if (!ok) {
				if (restore)
					restore_dvo(dvo);
				enable_dvo(dvo);
				restore = true;
			}
		} while (!ok);

		if (restore)
			restore_dvo(dvo);
	}
}

static void ns2501_dump_regs(struct intel_dvo_device *dvo)
{
	uint8_t val;

	ns2501_readb(dvo, NS2501_FREQ_LO, &val);
	DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
	ns2501_readb(dvo, NS2501_FREQ_HI, &val);
	DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
	ns2501_readb(dvo, NS2501_REG8, &val);
	DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
	ns2501_readb(dvo, NS2501_REG9, &val);
	DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
	ns2501_readb(dvo, NS2501_REGC, &val);
	DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
}

static void ns2501_destroy(struct intel_dvo_device *dvo)
{
	struct ns2501_priv *ns = dvo->dev_priv;

	if (ns) {
		kfree(ns);
		dvo->dev_priv = NULL;
	}
}

struct intel_dvo_dev_ops ns2501_ops = {
	.init = ns2501_init,
	.detect = ns2501_detect,
	.mode_valid = ns2501_mode_valid,
	.mode_set = ns2501_mode_set,
	.dpms = ns2501_dpms,
	.dump_regs = ns2501_dump_regs,
	.destroy = ns2501_destroy,
};
+80 −63
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@

enum {
	ACTIVE_LIST,
	FLUSHING_LIST,
	INACTIVE_LIST,
	PINNED_LIST,
};
@@ -62,28 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data)

	seq_printf(m, "gen: %d\n", info->gen);
	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
#define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
	B(is_mobile);
	B(is_i85x);
	B(is_i915g);
	B(is_i945gm);
	B(is_g33);
	B(need_gfx_hws);
	B(is_g4x);
	B(is_pineview);
	B(is_broadwater);
	B(is_crestline);
	B(has_fbc);
	B(has_pipe_cxsr);
	B(has_hotplug);
	B(cursor_needs_physical);
	B(has_overlay);
	B(overlay_needs_physical);
	B(supports_tv);
	B(has_bsd_ring);
	B(has_blt_ring);
	B(has_llc);
#undef B
#define DEV_INFO_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
#define DEV_INFO_SEP ;
	DEV_INFO_FLAGS;
#undef DEV_INFO_FLAG
#undef DEV_INFO_SEP

	return 0;
}
@@ -121,14 +103,15 @@ static const char *cache_level_str(int type)
static void
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{
	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s",
		   &obj->base,
		   get_pin_flag(obj),
		   get_tiling_flag(obj),
		   obj->base.size / 1024,
		   obj->base.read_domains,
		   obj->base.write_domain,
		   obj->last_rendering_seqno,
		   obj->last_read_seqno,
		   obj->last_write_seqno,
		   obj->last_fenced_seqno,
		   cache_level_str(obj->cache_level),
		   obj->dirty ? " dirty" : "",
@@ -177,10 +160,6 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
		seq_printf(m, "Inactive:\n");
		head = &dev_priv->mm.inactive_list;
		break;
	case FLUSHING_LIST:
		seq_printf(m, "Flushing:\n");
		head = &dev_priv->mm.flushing_list;
		break;
	default:
		mutex_unlock(&dev->struct_mutex);
		return -EINVAL;
@@ -238,7 +217,6 @@ static int i915_gem_object_info(struct seq_file *m, void* data)

	size = count = mappable_size = mappable_count = 0;
	count_objects(&dev_priv->mm.active_list, mm_list);
	count_objects(&dev_priv->mm.flushing_list, mm_list);
	seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
		   count, mappable_count, size, mappable_size);

@@ -413,7 +391,7 @@ static void i915_ring_seqno_info(struct seq_file *m,
{
	if (ring->get_seqno) {
		seq_printf(m, "Current sequence (%s): %d\n",
			   ring->name, ring->get_seqno(ring));
			   ring->name, ring->get_seqno(ring, false));
	}
}

@@ -630,12 +608,12 @@ static void print_error_buffers(struct seq_file *m,
	seq_printf(m, "%s [%d]:\n", name, count);

	while (count--) {
		seq_printf(m, "  %08x %8u %04x %04x %08x%s%s%s%s%s%s%s",
		seq_printf(m, "  %08x %8u %04x %04x %x %x%s%s%s%s%s%s%s",
			   err->gtt_offset,
			   err->size,
			   err->read_domains,
			   err->write_domain,
			   err->seqno,
			   err->rseqno, err->wseqno,
			   pin_flag(err->pinned),
			   tiling_flag(err->tiling),
			   dirty_flag(err->dirty),
@@ -799,10 +777,14 @@ i915_error_state_write(struct file *filp,
	struct seq_file *m = filp->private_data;
	struct i915_error_state_file_priv *error_priv = m->private;
	struct drm_device *dev = error_priv->dev;
	int ret;

	DRM_DEBUG_DRIVER("Resetting error state\n");

	mutex_lock(&dev->struct_mutex);
	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	i915_destroy_error_state(dev);
	mutex_unlock(&dev->struct_mutex);

@@ -1292,7 +1274,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)

	seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");

	for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->max_delay;
	for (gpu_freq = dev_priv->rps.min_delay;
	     gpu_freq <= dev_priv->rps.max_delay;
	     gpu_freq++) {
		I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
@@ -1472,8 +1455,12 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	mutex_lock(&dev->struct_mutex);
	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
	seq_printf(m, "bit6 swizzle for Y-tiling = %s\n",
@@ -1674,7 +1661,7 @@ i915_ring_stop_write(struct file *filp,
	struct drm_device *dev = filp->private_data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	char buf[20];
	int val = 0;
	int val = 0, ret;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
@@ -1689,7 +1676,10 @@ i915_ring_stop_write(struct file *filp,

	DRM_DEBUG_DRIVER("Stopping rings 0x%08x\n", val);

	mutex_lock(&dev->struct_mutex);
	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	dev_priv->stop_rings = val;
	mutex_unlock(&dev->struct_mutex);

@@ -1713,10 +1703,18 @@ i915_max_freq_read(struct file *filp,
	struct drm_device *dev = filp->private_data;
	drm_i915_private_t *dev_priv = dev->dev_private;
	char buf[80];
	int len;
	int len, ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	len = snprintf(buf, sizeof(buf),
		       "max freq: %d\n", dev_priv->max_delay * 50);
		       "max freq: %d\n", dev_priv->rps.max_delay * 50);
	mutex_unlock(&dev->struct_mutex);

	if (len > sizeof(buf))
		len = sizeof(buf);
@@ -1733,7 +1731,10 @@ i915_max_freq_write(struct file *filp,
	struct drm_device *dev = filp->private_data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	char buf[20];
	int val = 1;
	int val = 1, ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
@@ -1748,12 +1749,17 @@ i915_max_freq_write(struct file *filp,

	DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val);

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	/*
	 * Turbo will still be enabled, but won't go above the set value.
	 */
	dev_priv->max_delay = val / 50;
	dev_priv->rps.max_delay = val / 50;

	gen6_set_rps(dev, val / 50);
	mutex_unlock(&dev->struct_mutex);

	return cnt;
}
@@ -1773,10 +1779,18 @@ i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
	struct drm_device *dev = filp->private_data;
	drm_i915_private_t *dev_priv = dev->dev_private;
	char buf[80];
	int len;
	int len, ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	len = snprintf(buf, sizeof(buf),
		       "min freq: %d\n", dev_priv->min_delay * 50);
		       "min freq: %d\n", dev_priv->rps.min_delay * 50);
	mutex_unlock(&dev->struct_mutex);

	if (len > sizeof(buf))
		len = sizeof(buf);
@@ -1791,7 +1805,10 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
	struct drm_device *dev = filp->private_data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	char buf[20];
	int val = 1;
	int val = 1, ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
@@ -1806,12 +1823,17 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,

	DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val);

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	/*
	 * Turbo will still be enabled, but won't go below the set value.
	 */
	dev_priv->min_delay = val / 50;
	dev_priv->rps.min_delay = val / 50;

	gen6_set_rps(dev, val / 50);
	mutex_unlock(&dev->struct_mutex);

	return cnt;
}
@@ -1834,9 +1856,15 @@ i915_cache_sharing_read(struct file *filp,
	drm_i915_private_t *dev_priv = dev->dev_private;
	char buf[80];
	u32 snpcr;
	int len;
	int len, ret;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	mutex_lock(&dev_priv->dev->struct_mutex);
	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
	mutex_unlock(&dev_priv->dev->struct_mutex);

@@ -1862,6 +1890,9 @@ i915_cache_sharing_write(struct file *filp,
	u32 snpcr;
	int val = 1;

	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
		return -ENODEV;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
			return -EINVAL;
@@ -1925,16 +1956,11 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
{
	struct drm_device *dev = inode->i_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	if (INTEL_INFO(dev)->gen < 6)
		return 0;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;
	gen6_gt_force_wake_get(dev_priv);
	mutex_unlock(&dev->struct_mutex);

	return 0;
}
@@ -1947,16 +1973,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
	if (INTEL_INFO(dev)->gen < 6)
		return 0;

	/*
	 * It's bad that we can potentially hang userspace if struct_mutex gets
	 * forever stuck.  However, if we cannot acquire this lock it means that
	 * almost certainly the driver has hung, is not unload-able. Therefore
	 * hanging here is probably a minor inconvenience not to be seen my
	 * almost every user.
	 */
	mutex_lock(&dev->struct_mutex);
	gen6_gt_force_wake_put(dev_priv);
	mutex_unlock(&dev->struct_mutex);

	return 0;
}
@@ -2006,7 +2023,6 @@ static struct drm_info_list i915_debugfs_list[] = {
	{"i915_gem_gtt", i915_gem_gtt_info, 0},
	{"i915_gem_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
	{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
	{"i915_gem_request", i915_gem_request_info, 0},
@@ -2067,6 +2083,7 @@ int i915_debugfs_init(struct drm_minor *minor)
				  &i915_cache_sharing_fops);
	if (ret)
		return ret;

	ret = i915_debugfs_create(minor->debugfs_root, minor,
				  "i915_ring_stop",
				  &i915_ring_stop_fops);
+24 −2

File changed.

Preview size limit exceeded, changes collapsed.

Loading