/*
*/
/*
* Copyright (c) 2006-2007, 2013, Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*/
#include "drm_edid.h"
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "drm_dp_helper.h"
#include "drm_crtc_helper.h"
typedef struct {
typedef struct {
int dot_limit;
} intel_p2_t;
struct intel_limit {
};
/* FDI */
int
{
}
static inline u32 /* units of 100MHz */
{
} else
return 27;
}
};
};
};
};
.p2_slow = 10,
.p2_fast = 10
},
};
/* n.min 1->2 fix high resolution issue */
};
},
};
},
};
/* Pineview's Ncounter is a ring counter */
/* Pineview only has one combined m divider, which we treat as m2. */
};
};
/* Ironlake / Sandybridge
*
* the range value for them is (actual_value - 2).
*/
/* n.min 1->2 fix high resolution issue */
};
};
};
/* LVDS 100mhz refclk limits. */
};
};
};
};
};
int refclk)
{
if (intel_is_dual_link_lvds(dev)) {
if (refclk == 100000)
else
} else {
if (refclk == 100000)
else
}
} else
return limit;
}
{
if (intel_is_dual_link_lvds(dev))
else
} else /* The option is for other outputs */
return limit;
}
{
if (HAS_PCH_SPLIT(dev))
} else if (IS_PINEVIEW(dev)) {
else
} else if (IS_VALLEYVIEW(dev)) {
else
else
} else {
else
}
return limit;
}
/* m1 is reserved as 0 in Pineview, n is a ring counter */
{
}
{
}
{
}
/**
* Returns whether any output on the specified pipe is of the specified type
*/
{
return true;
return false;
}
/**
* Returns whether the given set of divisors are valid for a given refclk with
* the given connectors.
*/
const intel_limit_t *limit,
const intel_clock_t *clock)
{
INTELPllInvalid ("p1 out of range\n");
INTELPllInvalid ("p out of range\n");
INTELPllInvalid ("m2 out of range\n");
INTELPllInvalid ("m1 out of range\n");
INTELPllInvalid ("m1 <= m2\n");
INTELPllInvalid ("m out of range\n");
INTELPllInvalid ("n out of range\n");
INTELPllInvalid ("vco out of range\n");
/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
* connector, etc., rather than just a single range.
*/
INTELPllInvalid ("dot out of range\n");
return true;
}
static bool
{
/*
* For LVDS just rely on its current settings for dual-channel.
* We haven't figured out how to reliably set up different
*/
if (intel_is_dual_link_lvds(dev))
else
} else {
else
}
break;
int this_err;
&clock))
continue;
if (match_clock &&
clock.p != match_clock->p)
continue;
*best_clock = clock;
}
}
}
}
}
}
static bool
{
/*
* For LVDS just rely on its current settings for dual-channel.
* We haven't figured out how to reliably set up different
*/
if (intel_is_dual_link_lvds(dev))
else
} else {
else
}
int this_err;
&clock))
continue;
if (match_clock &&
clock.p != match_clock->p)
continue;
*best_clock = clock;
}
}
}
}
}
}
static bool
{
int max_n;
bool found;
/* approximately equals target * 0.00585 */
found = false;
if (intel_is_dual_link_lvds(dev))
else
} else {
else
}
/* based on hardware requirement prefer smaller n to precision */
/* based on hardware requirement prefer larger m1,m2 */
int this_err;
&clock))
continue;
*best_clock = clock;
found = true;
}
}
}
}
}
return found;
}
static bool
{
flag = 0;
bestppm = 1000000;
updrate = 0;
minupdate = 19200;
/* based on hardware requirement, prefer smaller n to precision */
if (p2 > 10)
/* based on hardware requirement, prefer bigger m1,m2 values */
bestppm = 0;
flag = 1;
}
flag = 1;
}
if (flag) {
bestn = n;
flag = 0;
}
}
}
}
}
}
best_clock->n = bestn;
return true;
}
{
}
{
DRM_DEBUG_KMS("vblank wait timed out\n");
}
/**
* intel_wait_for_vblank - wait for vblank on a given pipe
* @dev: drm device
* @pipe: pipe to wait for
*
* Wait for vblank to occur on a given pipe. Needed for various bits of
* mode setting code.
*/
{
return;
}
/* Clear existing vblank status. Note this will clear any other
* sticky status fields as well.
*
* This races with i915_driver_irq_handler() with the result
* that either function could miss a vblank event. Here it is not
* fatal, as we will either wait upon the next vblank interrupt or
* timeout. Generally speaking intel_wait_for_vblank() is only
* called during modeset at which time the GPU should be idle and
* should *not* be performing page flips and thus not waiting on
* vblanks...
* Currently, the result of us stealing a vblank from the irq
* handler is that a single frame will be skipped during swapbuffers.
*/
/* Wait for vblank interrupt bit to set */
50))
DRM_DEBUG_KMS("vblank wait timed out\n");
}
/*
* intel_wait_for_pipe_off - wait for pipe to turn off
* @dev: drm device
* @pipe: pipe to wait for
*
* After disabling a pipe, we can't wait for vblank in the usual way,
* spinning on the vblank interrupt status bit, since we won't actually
* see an interrupt when the pipe is disabled.
*
* On Gen4 and above:
* wait for the pipe register state bit to turn off
*
* Otherwise:
* wait for the display line value to settle (it usually
* ends up stopping at the start of the next frame).
*
*/
{
pipe);
/* Wait for the Pipe State to go off */
100))
DRM_ERROR("pipe_off wait timed out\n");
} else {
else
/* Wait for the display line to settle */
do {
mdelay(5);
DRM_ERROR("pipe_off wait timed out\n");
}
}
/*
* ibx_digital_port_connected - is the specified port connected?
* @dev_priv: i915 private structure
* @port: the port to test
*
* Returns true if @port is connected, false otherwise.
*/
struct intel_digital_port *port)
{
case PORT_B:
break;
case PORT_C:
break;
case PORT_D:
break;
default:
return true;
}
} else {
case PORT_B:
break;
case PORT_C:
break;
case PORT_D:
break;
default:
return true;
}
}
}
{
}
/* Only for pre-ILK configs */
{
int reg;
bool cur_state;
DRM_ERROR("PLL state assertion failure (expected %s, current %s)",
}
static struct intel_shared_dpll *
{
return NULL;
}
/* For ILK+ */
struct intel_shared_dpll *pll,
bool state)
{
bool cur_state;
DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
return;
}
if (!pll) {
return;
}
DRM_DEBUG_KMS("%s assertion failure (expected %s, current %s)",
}
{
int reg;
bool cur_state;
pipe);
/* On Haswell, DDI is used instead of FDI_TX_CTL */
} else {
}
DRM_ERROR("FDI TX state assertion failure (expected %s, current %s)\n",
}
{
int reg;
bool cur_state;
DRM_ERROR("FDI RX state assertion failure (expected %s, current %s)\n",
}
{
int reg;
/* ILK FDI PLL is always enabled */
return;
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
return;
if(!(val & FDI_TX_PLL_ENABLE))
DRM_ERROR("FDI TX PLL assertion failure, should be active but is disabled\n");
}
{
int reg;
if(!(val & FDI_RX_PLL_ENABLE))
DRM_ERROR("FDI RX PLL assertion failure, should be active but is disabled\n");
}
{
bool locked = true;
} else {
pp_reg = PP_CONTROL;
}
if (!(val & PANEL_POWER_ON) ||
locked = false;
panel_pipe = PIPE_B;
DRM_ERROR("panel assertion failure, pipe %c regs locked\n",
}
{
int reg;
bool cur_state;
pipe);
/* if we need the pipe A quirk it must be always on */
state = true;
cur_state = false;
} else {
}
DRM_ERROR("pipe %c assertion failure (expected %s, current %s)\n",
}
{
int reg;
bool cur_state;
DRM_ERROR("plane %c assertion failure, should be active but is disabled\n",
plane_name(plane));
}
{
int reg, i;
int cur_pipe;
/* Planes are fixed to pipes on ILK+ */
if(val & DISPLAY_PLANE_ENABLE)
DRM_ERROR("plane %c assertion failure, should be disabled but not\n",
plane_name(pipe));
return;
}
/* Need to check both planes against the pipe */
DRM_ERROR("plane %c assertion failure, should be off on pipe %c but is still active\n",
}
}
{
int reg, i;
if (IS_VALLEYVIEW(dev)) {
DRM_ERROR("sprite %c assertion failure, should be off on pipe %c but is still active\n",
}
if(val & SPRITE_ENABLE)
DRM_ERROR("sprite %c assertion failure, should be off on pipe %c but is still active\n",
if(val & DVS_ENABLE)
DRM_ERROR("sprite %c assertion failure, should be off on pipe %c but is still active\n",
}
}
{
bool enabled;
DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n");
return;
}
if(!enabled)
DRM_ERROR("PCH refclk assertion failure, should be active but is disabled\n");
}
{
int reg;
bool enabled;
if(enabled)
DRM_ERROR("transcoder assertion failed, should be off on pipe %c but is still active\n",
}
{
if ((val & DP_PORT_EN) == 0)
return false;
return false;
} else {
return false;
}
return true;
}
{
if ((val & SDVO_ENABLE) == 0)
return false;
return false;
} else {
return false;
}
return true;
}
{
if ((val & LVDS_PORT_EN) == 0)
return false;
return false;
} else {
return false;
}
return true;
}
{
if ((val & ADPA_DAC_ENABLE) == 0)
return false;
return false;
} else {
return false;
}
return true;
}
{
DRM_ERROR("PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
&& (val & DP_PIPEB_SELECT))
DRM_ERROR("IBX PCH dp port still using transcoder B\n");
}
{
DRM_ERROR("PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
&& (val & SDVO_PIPE_B_SELECT))
DRM_ERROR("IBX PCH hdmi port still using transcoder B\n");
}
{
int reg;
DRM_ERROR("PCH VGA enabled on transcoder %c, should be disabled\n",
DRM_ERROR("PCH LVDS enabled on transcoder %c, should be disabled\n",
}
/**
* intel_enable_pll - enable a PLL
* @dev_priv: i915 private structure
* @pipe: pipe PLL to enable
*
* Enable @pipe's PLL so we can start pumping pixels from a plane. Check to
* make sure the PLL reg is writable first though, since the panel write
* protect mechanism may be enabled.
*
* Note! This is for pre-ILK only.
*
* Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
*/
{
int reg;
/* No really, not for ILK+ */
/* PLL is protected by panel, make sure we can write it */
val |= DPLL_VCO_ENABLE;
/* We do this three times for luck */
}
/**
* intel_disable_pll - disable a PLL
* @dev_priv: i915 private structure
* @pipe: pipe PLL to disable
*
* Disable the PLL for @pipe, making sure the pipe is off first.
*
* Note! This is for pre-ILK only.
*/
{
int reg;
/* Don't disable pipe A or pipe A PLLs if needed */
return;
/* Make sure the pipe isn't still relying on us */
val &= ~DPLL_VCO_ENABLE;
}
{
if (!port)
else
DRM_ERROR("timed out waiting for port %c ready: 0x%08x\n",
}
/**
* ironlake_enable_pch_pll - enable PCH PLL
* @dev_priv: i915 private structure
* @pipe: pipe PLL to enable
*
* The PCH PLL needs to be enabled before the PCH transcoder, since it
* drives the transcoder clock.
*/
{
/* PCH PLLs only available on ILK, SNB and IVB */
DRM_ERROR("pll is NULL");
return;
}
DRM_ERROR("pll refcount equal to 0");
return;
}
DRM_DEBUG_KMS("enable %s (active %d, on? %d)for crtc %d\n",
return;
}
}
{
/* PCH only available on ILK+ */
DRM_ERROR("pll is NULL");
return;
}
DRM_ERROR("pll refcount equal to 0");
return;
}
DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
return;
}
return;
}
{
/* PCH only available on ILK+ */
/* Make sure PCH DPLL is enabled */
/* FDI must be feeding us bits for PCH ports */
if (HAS_PCH_CPT(dev)) {
/* Workaround: Set the timing override bit before enabling the
* pch transcoder. */
}
/*
* make the BPC in transcoder be consistent with
* that in pipeconf reg.
*/
val &= ~PIPECONF_BPC_MASK;
}
val &= ~TRANS_INTERLACE_MASK;
else
val |= TRANS_INTERLACED;
else
val |= TRANS_PROGRESSIVE;
}
enum transcoder cpu_transcoder)
{
/* PCH only available on ILK+ */
/* FDI must be feeding us bits for PCH ports */
/* Workaround: set timing override bit. */
val = TRANS_ENABLE;
if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
val |= TRANS_INTERLACED;
else
val |= TRANS_PROGRESSIVE;
DRM_ERROR("Failed to enable PCH transcoder\n");
}
{
/* FDI relies on the transcoder */
/* Ports must be off as well */
val &= ~TRANS_ENABLE;
/* wait for PCH transcoder off, transcoder state */
if (!HAS_PCH_IBX(dev)) {
/* Workaround: Clear the timing override chicken bit again. */
}
}
{
val &= ~TRANS_ENABLE;
/* wait for PCH transcoder off, transcoder state */
DRM_ERROR("Failed to disable PCH transcoder\n");
/* Workaround: clear timing override bit. */
}
/**
* intel_enable_pipe - enable a pipe, asserting requirements
* @dev_priv: i915 private structure
* @pipe: pipe to enable
* @pch_port: on ILK+, is this pipe driving a PCH port or not
*
* Enable @pipe, making sure that various hardware specific requirements
* are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
*
* @pipe should be %PIPE_A or %PIPE_B.
*
* Will wait until the pipe is actually running (i.e. first vblank) before
* returning.
*/
bool pch_port)
{
pipe);
int reg;
else
/*
* A pipe without a PLL won't actually be able to drive bits from
* a plane. On ILK+ the pipe PLLs are integrated, so we don't
* need the check.
*/
else {
if (pch_port) {
/* if driving the PCH, we need FDI enabled */
(enum pipe) cpu_transcoder);
}
/* FIXME: assert CPU port conditions for SNB+ */
}
if (val & PIPECONF_ENABLE)
return;
}
/**
* intel_disable_pipe - disable a pipe, asserting requirements
* @dev_priv: i915 private structure
* @pipe: pipe to disable
*
* Disable @pipe, making sure that various hardware specific requirements
* are met, if applicable, e.g. plane disabled, panel fitter off, etc.
*
* @pipe should be %PIPE_A or %PIPE_B.
*
* Will wait until the pipe has shut down before returning.
*/
{
pipe);
int reg;
/*
* Make sure planes won't keep trying to pump pixels to us,
* or we might hang the display.
*/
/* Don't disable pipe A or pipe A PLLs if needed */
return;
if ((val & PIPECONF_ENABLE) == 0)
return;
}
/*
* Plane regs are double buffered, going from enabled->disabled needs a
* trigger in order to latch. The display address reg provides this.
*/
{
else
}
/**
* intel_enable_plane - enable a display plane on a given pipe
* @dev_priv: i915 private structure
* @plane: plane to enable
* @pipe: pipe being fed
*
* Enable @plane on @pipe, making sure that @pipe is running first.
*/
{
int reg;
/* If the pipe isn't enabled, we can't pump pixels and may hang */
if (val & DISPLAY_PLANE_ENABLE)
return;
}
/**
* intel_disable_plane - disable a display plane
* @dev_priv: i915 private structure
* @plane: plane to disable
* @pipe: pipe consuming the data
*
* Disable @plane; should be an independent operation.
*/
{
int reg;
if ((val & DISPLAY_PLANE_ENABLE) == 0)
return;
}
{
#ifdef CONFIG_INTEL_IOMMU
return true;
#endif
return false;
}
int
struct drm_i915_gem_object *obj,
struct intel_ring_buffer *pipelined)
{
int ret;
switch (obj->tiling_mode) {
case I915_TILING_NONE:
else
break;
case I915_TILING_X:
/* pin() will align the object as required by fence */
alignment = 0;
break;
case I915_TILING_Y:
/* Despite that we check this in framebuffer_init userspace can
* screw us over and change the tiling after the fact. Only
* pinned buffers can't change their tiling. */
DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n");
return -EINVAL;
default:
BUG();
return -EINVAL;
}
/* Note that the w/a also requires 64 PTE of padding following the
* bo. We currently fill all unused PTE with the shadow page and so
* we should always have valid PTE following the scanout preventing
* the VT-d warning.
*/
if (ret)
goto err_interruptible;
/* Install a fence for tiled scan-out. Pre-i965 always needs a
* fence, whereas 965+ only requires a fence if using
* framebuffer compression. For simplicity, we always install
* a fence as the cost is not that onerous.
*/
if (ret)
goto err_unpin;
return 0;
return ret;
}
{
}
/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
* is assumed to be a power-of-two. */
unsigned long intel_gen4_compute_page_offset(int *x, int *y,
unsigned int tiling_mode,
unsigned int cpp,
unsigned int pitch)
{
if (tiling_mode != I915_TILING_NONE) {
tile_rows = *y / 8;
*y %= 8;
*x %= 512/cpp;
} else {
unsigned int offset;
*y = 0;
return offset & -4096;
}
}
int x, int y)
{
unsigned long linear_offset;
switch (plane) {
case 0:
case 1:
break;
default:
return -EINVAL;
}
/* Mask out pixel format bits in case we change it */
switch (fb->pixel_format) {
case DRM_FORMAT_C8:
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
break;
case DRM_FORMAT_RGB565:
break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
break;
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
break;
default:
return -EINVAL;
}
else
dspcntr &= ~DISPPLANE_TILED;
}
} else {
}
DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
} else
return 0;
}
struct drm_framebuffer *fb, int x, int y)
{
unsigned long linear_offset;
switch (plane) {
case 0:
case 1:
case 2:
break;
default:
return -EINVAL;
}
/* Mask out pixel format bits in case we change it */
switch (fb->pixel_format) {
case DRM_FORMAT_C8:
break;
case DRM_FORMAT_RGB565:
break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
break;
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
break;
default:
return -EINVAL;
}
else
dspcntr &= ~DISPPLANE_TILED;
/* must disable */
DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
if (IS_HASWELL(dev)) {
} else {
}
return 0;
}
/* Assume fb object is pinned & idle & fenced and just update base pointers */
static int
int x, int y, enum mode_set_atomic state)
{
}
{
/*
* Flips in the rings have been nuked by the reset,
* so complete all pending flips so that user space
* will get its events and not get stuck.
*
* Also update the base address of all primary
* planes to the the last fb to make sure we're
* showing the correct fb after a reset.
*
* Need to make two loops over the crtcs so that we
* don't try to grab a crtc mutex before the
* pending_flip_queue really got woken up.
*/
}
if (intel_crtc->active)
}
}
static int
{
int ret;
/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
* current scanout is retired before unpinning the old
* framebuffer.
*
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
return ret;
}
{
return;
if (!master_priv->sarea_priv)
return;
switch (intel_crtc->pipe) {
case 0:
break;
case 1:
break;
default:
break;
}
}
static int
struct drm_framebuffer *fb)
{
int ret;
/* no fb bound */
if (!fb) {
DRM_ERROR("No FB bound\n");
return 0;
}
DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n",
return -EINVAL;
}
NULL);
if (ret != 0) {
DRM_ERROR("pin & fence failed\n");
return ret;
}
if (ret) {
DRM_ERROR("failed to update base address\n");
return ret;
}
crtc->x = x;
crtc->y = y;
if (old_fb) {
}
intel_crtc_update_sarea_pos(crtc, x, y);
return 0;
}
{
/* enable normal train */
if (IS_IVYBRIDGE(dev)) {
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
}
if (HAS_PCH_CPT(dev)) {
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
}
/* wait one idle pattern time */
udelay(1000);
/* IVB wants error correction enabled */
if (IS_IVYBRIDGE(dev))
}
{
}
{
/*
* When everything is off disable fdi C so that we could enable fdi B
* with all lanes. Note that we don't care about enabled pipes without
* an enabled pch encoder.
*/
if (!pipe_has_enabled_pch(pipe_B_crtc) &&
DRM_DEBUG_KMS("disabling fdi C rx\n");
}
}
{
/* FDI needs bits from pipe & plane first */
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
temp &= ~FDI_RX_SYMBOL_LOCK;
temp &= ~FDI_RX_BIT_LOCK;
udelay(150);
/* enable CPU FDI TX and PCH FDI RX */
temp &= ~FDI_LINK_TRAIN_NONE;
temp &= ~FDI_LINK_TRAIN_NONE;
udelay(150);
/* Ironlake workaround, enable clock pointer after FDI enable*/
if ((temp & FDI_RX_BIT_LOCK)) {
DRM_DEBUG_KMS("FDI train 1 done.\n");
break;
}
}
if (tries == 5)
DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */
temp &= ~FDI_LINK_TRAIN_NONE;
temp &= ~FDI_LINK_TRAIN_NONE;
udelay(150);
if (temp & FDI_RX_SYMBOL_LOCK) {
DRM_DEBUG_KMS("FDI train 2 done.\n");
break;
}
}
if (tries == 5)
DRM_ERROR("FDI train 2 fail!\n");
DRM_DEBUG_KMS("FDI train done\n");
}
static const int snb_b_fdi_train_param [] = {
};
/* The FDI link training functions for SNB/Cougarpoint. */
{
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
temp &= ~FDI_RX_SYMBOL_LOCK;
temp &= ~FDI_RX_BIT_LOCK;
udelay(150);
/* enable CPU FDI TX and PCH FDI RX */
temp &= ~FDI_LINK_TRAIN_NONE;
/* SNB-B */
if (HAS_PCH_CPT(dev)) {
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
}
udelay(150);
for (i = 0; i < 4; i++ ) {
temp |= snb_b_fdi_train_param[i];
udelay(500);
if (temp & FDI_RX_BIT_LOCK) {
DRM_DEBUG_KMS("FDI train 1 done.\n");
break;
}
udelay(50);
}
if (retry < 5)
break;
}
if (i == 4)
DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */
temp &= ~FDI_LINK_TRAIN_NONE;
/* SNB-B */
}
if (HAS_PCH_CPT(dev)) {
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
}
udelay(150);
for (i = 0; i < 4; i++ ) {
temp |= snb_b_fdi_train_param[i];
udelay(500);
if (temp & FDI_RX_SYMBOL_LOCK) {
DRM_DEBUG_KMS("FDI train 2 done.\n");
break;
}
udelay(50);
}
if (retry < 5)
break;
}
if (i == 4)
DRM_ERROR("FDI train 2 fail!\n");
DRM_DEBUG_KMS("FDI train done.\n");
}
/* Manual link training for Ivy Bridge A0 parts */
{
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
temp &= ~FDI_RX_SYMBOL_LOCK;
temp &= ~FDI_RX_BIT_LOCK;
udelay(150);
DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
/* enable CPU FDI TX and PCH FDI RX */
temp &= ~FDI_LINK_TRAIN_AUTO;
udelay(150);
for (i = 0; i < 4; i++ ) {
temp |= snb_b_fdi_train_param[i];
udelay(500);
if (temp & FDI_RX_BIT_LOCK ||
DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i);
break;
}
}
if (i == 4)
DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */
udelay(150);
for (i = 0; i < 4; i++ ) {
temp |= snb_b_fdi_train_param[i];
udelay(500);
if (temp & FDI_RX_SYMBOL_LOCK) {
DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i);
break;
}
}
if (i == 4)
DRM_ERROR("FDI train 2 fail!\n");
DRM_DEBUG_KMS("FDI train done.\n");
}
{
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
udelay(200);
/* Switch from Rawclk to PCDclk */
udelay(200);
/* Enable CPU FDI TX PLL, always on for Ironlake */
if ((temp & FDI_TX_PLL_ENABLE) == 0) {
udelay(100);
}
}
{
/* Switch from PCDclk to Rawclk */
/* Disable CPU FDI TX PLL */
udelay(100);
/* Wait for the clocks to turn off. */
udelay(100);
}
{
/* disable CPU FDI tx and PCH FDI rx */
udelay(100);
/* Ironlake workaround, disable clock pointer after downing FDI */
if (HAS_PCH_IBX(dev)) {
}
/* still set train pattern 1 */
temp &= ~FDI_LINK_TRAIN_NONE;
if (HAS_PCH_CPT(dev)) {
} else {
temp &= ~FDI_LINK_TRAIN_NONE;
}
/* BPC in FDI rx is consistent with that in PIPECONF */
udelay(100);
}
{
unsigned long flags;
bool pending;
return false;
return pending;
}
{
/* LINTED */
int ret;
return;
}
/* Program iCLKIP clock to the desired frequency */
{
/* It is necessary to ungate the pixclk gate prior to programming
* the divisors, and gate it back when it is done.
*/
/* Disable SSCCTL */
SBI_ICLK);
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
auxdiv = 1;
divsel = 0x41;
phaseinc = 0x20;
} else {
/* The iCLK virtual clock root frequency is in MHz,
* but the crtc->mode.clock in in KHz. To get the divisors,
* it is necessary to divide one by another, so we
* convert the virtual clock precision to KHz here for higher
* precision.
*/
auxdiv = 0;
}
/* This should not happen with any sane values */
DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
phaseinc);
/* Program SSCDIVINTPHASE6 */
/* Program SSCAUXDIV */
/* Enable modulator and associated divider */
temp &= ~SBI_SSCCTL_DISABLE;
/* Wait for initialization time */
udelay(24);
}
enum pipe pch_transcoder)
{
}
/*
* Enable PCH resources required for PCH ports:
* - PCH PLLs
* - update transcoder timings
* - DP transcoding bits
* - transcoder
*/
{
/* Write the TU size bits before fdi link training, so that error
* detection works. */
/* For PCH output, training FDI link */
/* XXX: pch pll's can be enabled any time before we enable the PCH
* transcoder, and we actually should do this to not upset any PCH
* transcoder that already use the clock when we share it.
*
* Note that enable_pch_pll tries to do the right thing, but get_pch_pll
* unconditionally resets the pll - we need that to have the right LVDS
* enable sequence. */
if (HAS_PCH_CPT(dev)) {
else
}
/* set transcoder timing */
/* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) &&
temp &= ~(TRANS_DP_PORT_SEL_MASK |
temp |= (TRANS_DP_OUTPUT_ENABLE |
switch (intel_trans_dp_port_sel(crtc)) {
case PCH_DP_B:
break;
case PCH_DP_C:
break;
case PCH_DP_D:
break;
default:
BUG();
}
}
}
{
/* Set transcoder timing. */
}
{
return;
DRM_ERROR("bad PCH PLL refcount\n");
return;
}
DRM_ERROR("PCH PLL refcount is 0, but it's still active");
}
}
{
enum intel_dpll_id i;
if (pll) {
DRM_DEBUG_KMS("CRTC:%d dropping existing %s\n",
}
/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
goto found;
}
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
/* Only want to check enabled timings first */
continue;
DRM_DEBUG_KMS("CRTC:%d sharing existing %s (refcount %d, ative %d)\n",
goto found;
}
}
/* Ok no matching timings, maybe there's a free one? */
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
goto found;
}
}
return NULL;
/* Wait for the clocks to stabilize before rewriting the regs */
udelay(150);
}
return pll;
}
{
udelay(500);
}
}
{
/* Force use of hard-coded filter coefficients
* as some pre-programmed values are broken,
* e.g. x201.
*/
else
}
}
{
}
{
}
{
if (intel_crtc->active)
return;
intel_crtc->active = true;
if ((temp & LVDS_PORT_EN) == 0)
}
/* Note: FDI PLL enabling _must_ be done before we enable the
* enabling. */
} else {
}
if (encoder->pre_enable)
/*
* On ILK+ LUT must be loaded before the pipe is running but with
* clocks enabled
*/
intel_crtc_update_cursor(crtc, true);
if (HAS_PCH_CPT(dev))
/*
* There seems to be a race in PCH platform hw (at least on some
* outputs) where an enabled pipe still completes any pageflip right
* away (as if the pipe is off) instead of waiting for vblank. As soon
* as the first vblank happend, everything works as expected. Hence just
* wait for one vblank before returning to avoid strange things
* happening.
*/
}
/* IPS only exists on ULT machines and is tied to pipe A. */
{
}
{
return;
/* We can only enable IPS after we enable a plane and wait for a vblank.
* We guarantee that the plane is enabled by calling intel_enable_ips
* only after intel_enable_plane. And intel_enable_plane already waits
* for a vblank, so all we need to do here is to enable the IPS bit. */
}
{
return;
I915_WRITE(IPS_CTL, 0);
/* We need to wait for a vblank before we can disable the plane. */
}
{
if (intel_crtc->active)
return;
intel_crtc->active = true;
if (encoder->pre_enable)
/*
* On ILK+ LUT must be loaded before the pipe is running but with
* clocks enabled
*/
intel_crtc_update_cursor(crtc, true);
/*
* There seems to be a race in PCH platform hw (at least on some
* outputs) where an enabled pipe still completes any pageflip right
* away (as if the pipe is off) instead of waiting for vblank. As soon
* as the first vblank happend, everything works as expected. Hence just
* wait for one vblank before returning to avoid strange things
* happening.
*/
}
{
/* To avoid upsetting the power well on haswell only disable the pfit if
* it's in use. The hw state code will make sure we get this right. */
}
}
{
if (!intel_crtc->active)
return;
intel_crtc_update_cursor(crtc, false);
if (encoder->post_disable)
if (HAS_PCH_CPT(dev)) {
/* disable TRANS_DP_CTL */
temp &= ~(TRANS_DP_OUTPUT_ENABLE |
/* disable DPLL_SEL */
}
/* disable PCH DPLL */
}
intel_crtc->active = false;
}
{
if (!intel_crtc->active)
return;
/* FBC must be disabled before disabling the plane on HSW. */
intel_crtc_update_cursor(crtc, false);
if (encoder->post_disable)
}
intel_crtc->active = false;
}
{
}
{
}
{
}
/* Let userspace switch the overlay on again. In most cases userspace
* has to recompute where to put it anyway.
*/
}
/**
* i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
* cursor plane briefly if not already running after enabling the display
* plane.
* This workaround avoids occasional blank screens when self refresh is
* enabled.
*/
static void
{
if ((cntl & CURSOR_MODE) == 0) {
}
}
{
return;
/*
* The panel fitter should only be adjusted whilst the pipe is disabled,
* according to register description and PRM.
*/
/* Border color in case we don't scale up to the full screen. Black by
* default, change to something else for debugging. */
}
{
if (intel_crtc->active)
return;
intel_crtc->active = true;
if (encoder->pre_pll_enable)
if (encoder->pre_enable)
/* VLV wants encoder enabling _before_ the pipe is up. */
intel_crtc_update_cursor(crtc, true);
}
{
if (intel_crtc->active)
return;
intel_crtc->active = true;
if (encoder->pre_enable)
/* The fixup needs to happen before cursor is enabled */
intel_crtc_update_cursor(crtc, true);
/* Give the overlay scaler a chance to enable if it's on this pipe */
intel_crtc_dpms_overlay(intel_crtc, true);
}
{
return;
DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
I915_WRITE(PFIT_CONTROL, 0);
}
{
if (!intel_crtc->active)
return;
/* Give the overlay scaler a chance to disable if it's on this pipe */
intel_crtc_dpms_overlay(intel_crtc, false);
intel_crtc_update_cursor(crtc, false);
if (encoder->post_disable)
intel_crtc->active = false;
}
{
}
bool enabled)
{
return;
if (!master_priv->sarea_priv)
return;
switch (pipe) {
case 0:
break;
case 1:
break;
default:
break;
}
}
/**
* Sets the power management mode of the pipe and plane.
*/
{
bool enable = false;
if (enable)
else
}
{
/* crtc should still be enabled when we disable it. */
intel_crtc->eld_vld = false;
intel_crtc_update_sarea(crtc, false);
}
/* Update computed state. */
continue;
continue;
}
}
{
}
}
{
}
/* Simple dpms helper for encodres with just one connector, no cloning and only
* one kind of off state. It clamps all !ON modes to fully OFF and changes the
* state of the entire output pipe. */
{
if (mode == DRM_MODE_DPMS_ON) {
encoder->connectors_active = true;
} else {
encoder->connectors_active = false;
}
}
/* Cross check the actual hw state with our own modeset state tracking (and it's
* internal consistency). */
{
bool encoder_enabled;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
DRM_ERROR("wrong connector dpms state\n");
DRM_ERROR("active connector not linked to encoder\n");
if (!encoder->connectors_active)
DRM_ERROR("encoder->connectors_active not set\n");
if (!encoder_enabled)
DRM_ERROR("encoder not enabled\n");
DRM_ERROR("crtc is NULL");
return;
}
DRM_ERROR("crtc not enabled\n");
DRM_ERROR("crtc not active\n");
DRM_ERROR("encoder active on the wrong pipe\n");
}
}
/* Even simpler default implementation, if there's really no special case to
* consider. */
{
/* All the simple cases only support two dpms states. */
if (mode != DRM_MODE_DPMS_ON)
return;
/* Only need to change hw state when actually enabled */
/* LINTED */
else
}
/* Simple connector->get_hw_state implementation for encoders that support only
* one connector and no cloning and hence the encoder state determines the state
* of the connector. */
{
}
struct intel_crtc_config *pipe_config)
{
DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n",
DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n",
return false;
}
if (IS_HASWELL(dev)) {
DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
return false;
} else {
return true;
}
}
return true;
/* Ivybridge 3 pipe is really complicated */
switch (pipe) {
case PIPE_A:
return true;
case PIPE_B:
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
return false;
}
return true;
case PIPE_C:
if (!pipe_has_enabled_pch(pipe_B_crtc) ||
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
return false;
}
} else {
DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
return false;
}
return true;
default:
BUG();
}
return false;
}
int i915_lane_workaround = 0;
struct intel_crtc_config *pipe_config)
{
/* FDI is a binary signal running at ~2.7GHz, encoding
* each output octet as 10 bits. The actual frequency
* is stored as a divider into a 100MHz clock, and the
* mode pixel clock is stored in units of 1KHz.
* Hence the bw of each lane in terms of the mode signal
* is:
*/
if (i915_lane_workaround)
else
DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
needs_recompute = true;
pipe_config->bw_constrained = true;
goto retry;
}
if (needs_recompute)
return RETRY;
}
struct intel_crtc_config *pipe_config)
{
}
struct intel_crtc_config *pipe_config)
{
if (HAS_PCH_SPLIT(dev)) {
/* FDI link clock is fixed at 2.7G */
> IRONLAKE_FDI_FREQ * 4)
return -EINVAL;
}
/* All interlaced capable intel hw wants timings in frames. Note though
* that intel_lvds_mode_fixup does some funny tricks with the crtc
* timings, so we need to be careful not to clobber these.*/
if (!pipe_config->timings_set)
/* Cantiga+ cannot handle modes with a hsync front porch of 0.
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
*/
return -EINVAL;
/* only a 8bpc pipe, with 6bpc dither through the panel fitter
* for lvds. */
}
/* XXX: PCH clock sharing is done in ->mode_set, so make sure the old
* clock survives for now. */
if (pipe_config->has_pch_encoder)
return 0;
}
{
return 400000; /* FIXME */
}
/* LINTED */
{
return 400000;
}
/* LINTED */
{
return 333000;
}
/* LINTED */
{
return 200000;
}
{
if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
return 133000;
else {
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
case GC_DISPLAY_CLOCK_333_MHZ:
return 333000;
default:
return 190000;
}
}
}
/* LINTED */
{
return 266000;
}
/* LINTED */
{
/* Assume that the hardware is in the high speed state. This
* should be the default.
*/
switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
case GC_CLOCK_133_200:
case GC_CLOCK_100_200:
return 200000;
case GC_CLOCK_166_250:
return 250000;
case GC_CLOCK_100_133:
return 133000;
}
/* Shouldn't happen */
return 0;
}
/* LINTED */
{
return 133000;
}
static void
{
while (*num > DATA_LINK_M_N_MASK ||
*den > DATA_LINK_M_N_MASK) {
*num >>= 1;
*den >>= 1;
}
}
static unsigned int
roundup_pow_of_two(unsigned int n)
{
unsigned int ret_val = 0;
unsigned int temp = n;
if (n == 0)
return 0;
while (temp != 1) {
ret_val++;
}
if ((1 << ret_val) ^ n)
ret_val++;
return (1 << ret_val);
}
static void compute_m_n(unsigned int m, unsigned int n,
{
}
void
int pixel_clock, int link_clock,
struct intel_link_m_n *m_n)
{
}
{
if (i915_panel_use_ssc >= 0)
return i915_panel_use_ssc != 0;
}
/* LINTED */
{
#if 0
#endif
return 100000; /* only one validated so far */
/*
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
refclk = 96000;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
if (intel_panel_use_ssc(dev_priv))
refclk = 100000;
else
refclk = 96000;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
refclk = 100000;
}
return refclk;
*/
}
{
int refclk;
if (IS_VALLEYVIEW(dev)) {
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
refclk / 1000);
refclk = 96000;
} else {
refclk = 48000;
}
return refclk;
}
{
}
{
}
{
if (IS_PINEVIEW(dev)) {
if (reduced_clock)
} else {
if (reduced_clock)
}
crtc->lowfreq_avail = false;
reduced_clock && i915_powersave) {
crtc->lowfreq_avail = true;
} else {
}
}
{
/*
* PLLB opamp always calibrates to max value of 0x3f, force enable it
* and set it to a reasonable value instead.
*/
reg_val &= 0xffffff00;
reg_val |= 0x00000030;
reg_val &= 0x8cffffff;
reg_val = 0x8c000000;
reg_val &= 0xffffff00;
reg_val &= 0x00ffffff;
reg_val |= 0xb0000000;
}
struct intel_link_m_n *m_n)
{
}
struct intel_link_m_n *m_n)
{
} else {
}
}
{
else
}
{
/* See eDP HDMI DPIO driver vbios notes doc */
/* PLL B needs special handling */
if (pipe)
/* Set up Tx target for periodic Rcomp update */
/* Disable target IRef on PLL */
reg_val &= 0x00ffffff;
/* Disable fast lock */
/* Set idtafcrecal before PLL is enabled */
/*
* Post divider depends on pixel clock rate, DAC vs digital (and LVDS,
* but we don't support that).
* Note: don't use the DAC post divider as it seems unstable.
*/
/* Set HBR and RBR LPF coefficients */
0x005f0021);
else
0x00d0000f);
/* Use SSC source */
if (!pipe)
0x0df40000);
else
0x0df70000);
} else { /* HDMI or VGA */
/* Use bend source */
if (!pipe)
0x0df70000);
else
0x0df40000);
}
coreclk |= 0x01000000;
if (encoder->pre_pll_enable)
/* Enable DPIO clock input */
if (pipe)
dpll |= DPLL_VCO_ENABLE;
udelay(150);
}
int num_connectors)
{
bool is_sdvo;
dpll |= DPLLB_MODE_LVDS;
else
}
if (is_sdvo)
/* compute bitmask from p1 value */
if (IS_PINEVIEW(dev))
else {
}
case 5:
break;
case 7:
break;
case 10:
break;
case 14:
break;
}
else
dpll |= DPLL_VCO_ENABLE;
udelay(150);
if (encoder->pre_pll_enable)
/* Wait for the clocks to stabilize. */
udelay(150);
} else {
/* The pixel multiplier can only be updated once the
* DPLL is enabled and the clocks are stable.
*
* So write it again.
*/
}
}
int num_connectors)
{
} else {
else
}
else
dpll |= DPLL_VCO_ENABLE;
udelay(150);
if (encoder->pre_pll_enable)
/* Wait for the clocks to stabilize. */
udelay(150);
/* The pixel multiplier can only be updated once the
* DPLL is enabled and the clocks are stable.
*
* So write it again.
*/
}
{
/* We need to be careful not to changed the adjusted mode, for otherwise
* the hw state checker will get angry at the mismatch. */
/* the chip adds 2 halflines automatically */
crtc_vtotal -= 1;
crtc_vblank_end -= 1;
} else {
vsyncshift = 0;
}
/* Workaround: when the EDP input selection is B, the VTOTAL_B must be
* programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is
* documented on the DDI_FUNC_CTL register description, EDP Input Select
* bits. */
/* pipesrc controls the size that is scaled from, which should
* always be the user's requested size.
*/
}
struct intel_crtc_config *pipe_config)
{
}
}
{
pipeconf = 0;
/* Enable pixel doubling when the dot clock is > 90% of the (display)
* core speed.
*
* XXX: No double-wide on 915GM pipe B. Is that the only reason for the
* pipe == 0 check?
*/
}
/* Bspec claims that we can't use dithering for 30bpp pipes. */
case 18:
break;
case 24:
break;
case 30:
break;
default:
/* Case prevented by intel_choose_pipe_bpp_dither. */
BUG();
}
}
if (HAS_PIPE_CXSR(dev)) {
if (intel_crtc->lowfreq_avail) {
DRM_DEBUG_KMS("enabling CxSR downclocking\n");
} else {
DRM_DEBUG_KMS("disabling CxSR downclocking\n");
}
}
else
}
int x, int y,
struct drm_framebuffer *fb)
{
bool is_lvds = false;
int ret;
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
}
/*
* Returns a set of divisors for the desired target clock with the given
* refclk, or FALSE. The returned values represent the clock equation:
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
*/
DRM_ERROR("Couldn't find PLL settings for mode!\n");
return -EINVAL;
}
/* Ensure that the cursor is valid for the new mode before changing... */
intel_crtc_update_cursor(crtc, true);
/*
* Ensure we match the reduced clock's P to the target clock.
* If the clocks don't match, we can't switch the display clock
* downclock feature.
*/
}
/* Compat-code for transition, will disappear. */
}
else if (IS_VALLEYVIEW(dev))
else
/* Set up the display plane register */
if (!IS_VALLEYVIEW(dev)) {
if (pipe == 0)
else
}
/* pipesrc and dspsize control the size that is scaled from,
* which should always be the user's requested size.
*/
return ret;
}
struct intel_crtc_config *pipe_config)
{
if (!(tmp & PFIT_ENABLE))
return;
/* Check whether the pfit is attached to our pipe. */
return;
} else {
return;
}
}
struct intel_crtc_config *pipe_config)
{
if (!(tmp & PIPECONF_ENABLE))
return false;
>> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
((tmp & SDVO_MULTIPLIER_MASK)
>> SDVO_MULTIPLIER_SHIFT_HIRES) + 1;
} else {
* port and will be fixed up in the encoder->get_config
* function. */
}
return true;
}
{
bool has_lvds = false;
bool has_cpu_edp = false;
bool has_panel = false;
bool has_ck505 = false;
bool can_ssc = false;
/* We need to take the global config into account */
case INTEL_OUTPUT_LVDS:
has_panel = true;
has_lvds = true;
break;
case INTEL_OUTPUT_EDP:
has_panel = true;
has_cpu_edp = true;
break;
}
}
if (HAS_PCH_IBX(dev)) {
} else {
has_ck505 = false;
can_ssc = true;
}
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
/* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after
* PCH B stepping, previous chipset stepping should be
* ignoring this setting.
*/
* compute the final state we want first and check if we need to
* make any changes at all.
*/
if (has_ck505)
else
final &= ~DREF_SSC1_ENABLE;
if (has_panel) {
if (has_cpu_edp) {
else
} else
} else {
}
return;
/* Always enable nonspread source */
if (has_ck505)
else
if (has_panel) {
val &= ~DREF_SSC_SOURCE_MASK;
/* SSC must be turned on before enabling the CPU output */
DRM_DEBUG_KMS("Using SSC on panel\n");
val |= DREF_SSC1_ENABLE;
} else
val &= ~DREF_SSC1_ENABLE;
/* Get SSC going before enabling the outputs */
udelay(200);
/* Enable CPU source on CPU attached eDP */
if (has_cpu_edp) {
DRM_DEBUG_KMS("Using SSC on eDP\n");
}
else
} else
udelay(200);
} else {
DRM_DEBUG_KMS("Disabling SSC entirely\n");
/* Turn off CPU output */
udelay(200);
/* Turn off the SSC source */
val &= ~DREF_SSC_SOURCE_MASK;
/* Turn off SSC1 */
val &= ~DREF_SSC1_ENABLE;
udelay(200);
}
}
/* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */
{
bool has_vga = false;
bool is_sdv = false;
case INTEL_OUTPUT_ANALOG:
has_vga = true;
break;
}
}
if (!has_vga)
return;
/* XXX: Rip out SDV support once Haswell ships for real. */
is_sdv = true;
tmp &= ~SBI_SSCCTL_DISABLE;
udelay(24);
tmp &= ~SBI_SSCCTL_PATHALT;
if (!is_sdv) {
DRM_ERROR("FDI mPHY reset assert timeout\n");
FDI_MPHY_IOSFSB_RESET_STATUS) == 0,
1))
DRM_ERROR("FDI mPHY reset de-assert timeout\n");
}
if (is_sdv) {
tmp |= 0x7FFF;
}
if (is_sdv) {
}
if (!is_sdv) {
}
tmp &= ~0xFF;
tmp |= 0x1C;
tmp &= ~0xFF;
tmp |= 0x1C;
if (!is_sdv) {
}
/* ULT uses SBI_GEN0, but ULT doesn't have VGA, so we don't care. */
tmp |= SBI_DBUFF0_ENABLE;
}
/*
* Initialize reference clocks when the driver loads
*/
{
else if (HAS_PCH_LPT(dev))
}
{
int num_connectors = 0;
bool is_lvds = false;
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
}
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
}
return 120000;
}
{
val = 0;
case 18:
val |= PIPECONF_6BPC;
break;
case 24:
val |= PIPECONF_8BPC;
break;
case 30:
val |= PIPECONF_10BPC;
break;
case 36:
val |= PIPECONF_12BPC;
break;
default:
/* Case prevented by intel_choose_pipe_bpp_dither. */
BUG();
}
else
}
/*
* Set up the pipe CSC unit.
*
* Currently only full range RGB to limited range RGB conversion
* is supported, but eventually this should handle various
* RGB<->YCbCr scenarios as well.
*/
{
/*
* TODO: Check what kind of values actually come out of the pipe
* accuracy. Perhaps we even need to take the bpc value into
* consideration.
*/
/*
* to BSpec, but reality doesn't agree. Just set them up in
* a way that results in the correct picture.
*/
} else {
}
}
{
val = 0;
else
}
bool *has_reduced_clock,
{
int refclk;
switch (intel_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
}
/*
* Returns a set of divisors for the desired target clock with the given
* refclk, or FALSE. The returned values represent the clock equation:
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
*/
if (!ret)
return false;
/*
* Ensure we match the reduced clock's P to the target clock.
* If the clocks don't match, we can't switch the display clock
* downclock feature.
*/
}
return true;
}
{
if (temp & FDI_BC_BIFURCATION_SELECT)
return;
DRM_DEBUG_KMS("enabling fdi C rx\n");
}
{
switch (intel_crtc->pipe) {
case PIPE_A:
break;
case PIPE_B:
} else
break;
case PIPE_C:
break;
default:
BUG();
}
}
{
/*
* Account for spread spectrum to avoid
* oversubscribing the link. Max center spread
* is 2.5%; use 5% for safety's sake.
*/
}
{
}
{
switch (intel_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
case INTEL_OUTPUT_SDVO:
case INTEL_OUTPUT_HDMI:
is_sdvo = true;
break;
}
}
/* Enable autotuning of the PLL clock (if permissible) */
factor = 21;
if (is_lvds) {
if ((intel_panel_use_ssc(dev_priv) &&
factor = 25;
factor = 20;
*fp |= FP_CB_TUNE;
*fp2 |= FP_CB_TUNE;
dpll = 0;
if (is_lvds)
dpll |= DPLLB_MODE_LVDS;
else
if (is_sdvo)
/* compute bitmask from p1 value */
/* also FPA1 */
case 5:
break;
case 7:
break;
case 10:
break;
case 14:
break;
}
else
return dpll | DPLL_VCO_ENABLE;
}
int x, int y,
struct drm_framebuffer *fb)
{
int num_connectors = 0;
bool is_lvds = false;
int ret;
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
}
DRM_ERROR("Couldn't find PLL settings for mode!\n");
return -EINVAL;
}
/* Compat-code for transition, will disappear. */
}
/* Ensure that the cursor is valid for the new mode before changing... */
intel_crtc_update_cursor(crtc, true);
/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
if (has_reduced_clock)
&fp, &reduced_clock,
if (has_reduced_clock)
else
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
return -EINVAL;
}
} else
if (encoder->pre_pll_enable)
intel_crtc->lowfreq_avail = true;
else
intel_crtc->lowfreq_avail = false;
/*
* We previously verified the shared_dpll in the eDP case,
* so pll should not be NULL from above call.
*/
return -EINVAL;
/* Wait for the clocks to stabilize. */
udelay(150);
/* The pixel multiplier can only be updated once the
* DPLL is enabled and the clocks are stable.
*
* So write it again.
*/
if (has_reduced_clock)
else
}
}
if (IS_IVYBRIDGE(dev))
/* Set up the display plane register */
return ret;
}
struct intel_crtc_config *pipe_config)
{
& ~TU_SIZE_MASK;
}
struct intel_crtc_config *pipe_config)
{
/* We currently do not free assignements of panel fitters on
* differentiates them) so just WARN about this case for now. */
}
}
}
struct intel_crtc_config *pipe_config)
{
if (!(tmp & PIPECONF_ENABLE))
return false;
/* LINTED */
pipe_config->has_pch_encoder = true;
FDI_DP_PORT_WIDTH_SHIFT) + 1;
/* XXX: Can't properly read out the pch dpll pixel multiplier
* since we don't have state tracking for pch clocks yet. */
} else {
else
}
&pipe_config->dpll_hw_state));
} else {
}
return true;
}
{
bool enable = false;
continue;
enable = true;
}
}
int x, int y,
struct drm_framebuffer *fb)
{
int ret;
if (!intel_ddi_pll_mode_set(crtc))
return -EINVAL;
/* Ensure that the cursor is valid for the new mode before changing... */
intel_crtc_update_cursor(crtc, true);
intel_crtc->lowfreq_avail = false;
}
/* Set up the display plane register */
return ret;
}
struct intel_crtc_config *pipe_config)
{
if (tmp & TRANS_DDI_FUNC_ENABLE) {
switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
default:
DRM_ERROR("unknown pipe linked to edp transcoder\n");
case TRANS_DDI_EDP_INPUT_A_ON:
break;
break;
break;
}
}
return false;
if (!(tmp & PIPECONF_ENABLE))
return false;
/*
* DDI E. So just check whether this pipe is wired to DDI E and whether
* the PCH transcoder is on.
*/
pipe_config->has_pch_encoder = true;
FDI_DP_PORT_WIDTH_SHIFT) + 1;
}
return true;
}
int x, int y,
struct drm_framebuffer *fb)
{
int ret;
if (ret != 0)
return ret;
DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
} else {
}
}
return 0;
}
int reg_edid)
{
uint32_t i;
i &= bits_eldv;
if (!eld[0])
return !i;
if (!i)
return false;
i &= ~bits_elda;
I915_WRITE(reg_elda, i);
for (i = 0; i < eld[2]; i++)
return false;
return true;
}
{
uint32_t i;
i = I915_READ(G4X_AUD_VID_DID);
if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
else
return;
i = I915_READ(G4X_AUD_CNTL_ST);
i &= ~(eldv | G4X_ELD_ADDR);
if (!eld[0])
return;
for (i = 0; i < len; i++)
i = I915_READ(G4X_AUD_CNTL_ST);
i |= eldv;
}
{
uint32_t i;
int len;
int tmp;
DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
/* Audio output enable */
DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
/* Wait for 1 vertical blank */
/* Set ELD valid state */
/* Enable HDMI mode */
/* clear N_programing_enable and N_value_index */
intel_crtc->eld_vld = true;
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
} else
I915_WRITE(aud_config, 0);
return;
i = I915_READ(aud_cntrl_st2);
i &= ~eldv;
I915_WRITE(aud_cntrl_st2, i);
if (!eld[0])
return;
i = I915_READ(aud_cntl_st);
i &= ~IBX_ELD_ADDRESS;
I915_WRITE(aud_cntl_st, i);
DRM_DEBUG_DRIVER("port num:%d\n", i);
for (i = 0; i < len; i++)
i = I915_READ(aud_cntrl_st2);
i |= eldv;
I915_WRITE(aud_cntrl_st2, i);
}
{
uint32_t i;
int len;
int hdmiw_hdmiedid;
int aud_config;
int aud_cntl_st;
int aud_cntrl_st2;
} else {
}
i = I915_READ(aud_cntl_st);
if (!i) {
DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
/* operate blindly on all ports */
} else {
}
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
} else
I915_WRITE(aud_config, 0);
return;
i = I915_READ(aud_cntrl_st2);
i &= ~eldv;
I915_WRITE(aud_cntrl_st2, i);
if (!eld[0])
return;
i = I915_READ(aud_cntl_st);
i &= ~IBX_ELD_ADDRESS;
I915_WRITE(aud_cntl_st, i);
for (i = 0; i < len; i++)
i = I915_READ(aud_cntrl_st2);
i |= eldv;
I915_WRITE(aud_cntrl_st2, i);
}
struct drm_display_mode *mode)
{
if (!connector)
return;
DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
}
{
int i;
bool reenable_ips = false;
/* The clocks have to be on to load the palette. */
return;
/* use legacy palette for Ironlake */
if (HAS_PCH_SPLIT(dev))
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
*/
reenable_ips = true;
}
for (i = 0; i < 256; i++) {
intel_crtc->lut_b[i]);
}
if (reenable_ips)
}
{
return;
if (visible) {
/* On these chipsets we can only modify the base whilst
* the cursor is disabled.
*/
cntl &= ~(CURSOR_FORMAT_MASK);
/* XXX width must be 64, stride 256 => 0x00 << 28 */
cntl |= CURSOR_ENABLE |
} else
}
{
if (base) {
} else {
}
}
/* and commit changes on next vblank */
}
{
if (base) {
cntl &= ~CURSOR_MODE;
} else {
}
if (IS_HASWELL(dev))
}
/* and commit changes on next vblank */
}
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
bool on)
{
int x = intel_crtc->cursor_x;
int y = intel_crtc->cursor_y;
bool visible;
pos = 0;
base = 0;
base = 0;
} else
base = 0;
if (x < 0) {
if (x + intel_crtc->cursor_width < 0)
base = 0;
x = -x;
}
pos |= x << CURSOR_X_SHIFT;
if (y < 0) {
if (y + intel_crtc->cursor_height < 0)
base = 0;
y = -y;
}
pos |= y << CURSOR_Y_SHIFT;
return;
} else {
else
}
}
{
int ret;
/* if we want to turn off the cursor ignore width and height */
if (!handle) {
DRM_DEBUG_KMS("cursor off\n");
addr = 0;
goto finish;
}
/* Currently we only support 64x64 cursors */
DRM_ERROR("we currently only support 64x64 cursors\n");
return -EINVAL;
}
return -ENOENT;
DRM_ERROR("buffer is to small\n");
goto fail;
}
/* we only need to pin inside GTT if cursor is non-phy */
unsigned alignment;
if (obj->tiling_mode) {
DRM_ERROR("cursor cannot be tiled\n");
goto fail_locked;
}
/* Note that the w/a also requires 2 PTE of padding following
* the bo. We currently fill all unused PTE with the shadow
* page and so we should always have valid PTE following the
* cursor preventing the VT-d warning.
*/
alignment = 0;
if (need_vtd_wa(dev))
if (ret) {
DRM_ERROR("failed to move cursor bo into the GTT\n");
goto fail_locked;
}
if (ret) {
DRM_ERROR("failed to release fence for cursor");
goto fail_unpin;
}
} else {
align);
if (ret) {
DRM_ERROR("failed to attach phys object\n");
goto fail_locked;
}
}
if (intel_crtc->cursor_bo) {
} else
}
return 0;
fail:
return ret;
}
{
return 0;
}
/** Sets the color ramps on behalf of RandR */
{
}
{
}
{
}
}
/* VESA 640x480x72Hz mode to set on the pipe */
};
static struct drm_framebuffer *
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj)
{
int ret;
if (!intel_fb) {
return (NULL);
}
if (ret) {
return (NULL);
}
}
static u32
{
}
static u32
{
}
static struct drm_framebuffer *
struct drm_display_mode *mode,
{
return (NULL);
bpp);
}
static struct drm_framebuffer *
struct drm_display_mode *mode)
{
return NULL;
return NULL;
fb->bits_per_pixel))
return NULL;
return NULL;
return fb;
}
struct drm_display_mode *mode,
struct intel_load_detect_pipe *old)
{
int i = -1;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
/*
* Algorithm gets a little messy:
*
* - if the connector already has an assigned crtc, use it (but make
* sure it's on first)
*
* - try to find the first unused crtc that can drive this connector,
* and use that if we find one
*/
/* See if we already have a CRTC for this connector */
/* Make sure the crtc and connector are running */
old->load_detect_temp = false;
/* Make sure the crtc and connector are running */
return true;
}
/* Find an unused one (if possible) */
i++;
continue;
if (!possible_crtc->enabled) {
break;
}
}
/*
* If we didn't find an unused CRTC, don't use any.
*/
if (!crtc) {
DRM_DEBUG_KMS("no pipe available for load-detect\n");
return false;
}
old->load_detect_temp = true;
if (!mode)
mode = &load_detect_mode;
/* We need a framebuffer large enough to accommodate all accesses
* that the plane may generate whilst we perform load detection.
* We can not rely on the fbcon either being present (we get called
* during its initialisation to detect all boot displays, or it may
* not even exist) or that it is large enough to satisfy the
* requested mode.
*/
DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
} else
DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
return false;
}
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
if (old->release_fb)
return false;
}
/* let the connector get through one full cycle before testing */
return true;
}
struct intel_load_detect_pipe *old)
{
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
if (old->load_detect_temp) {
if (old->release_fb) {
}
return;
}
/* Switch crtc and encoder back off if necessary */
}
/* Returns the clock of the currently programmed mode of the given pipe. */
{
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
else
if (IS_PINEVIEW(dev)) {
} else {
}
if (IS_PINEVIEW(dev))
else
switch (dpll & DPLL_MODE_MASK) {
case DPLLB_MODE_DAC_SERIAL:
5 : 10;
break;
case DPLLB_MODE_LVDS:
7 : 14;
break;
default:
DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
return 0;
}
if (IS_PINEVIEW(dev))
else
} else {
if (is_lvds) {
if ((dpll & PLL_REF_INPUT_MASK) ==
/* XXX: might not be 66MHz */
} else
} else {
if (dpll & PLL_P1_DIVIDE_BY_TWO)
else {
}
if (dpll & PLL_P2_DIVIDE_BY_4)
else
}
}
/* XXX: It would be nice to validate the clocks, but we can't reuse
* i830PllIsValid() because it relies on the xf86_config connector
* configuration being accurate, which it isn't necessarily.
*/
}
/** Returns the currently programmed mode of the given pipe. */
{
if (!mode)
return NULL;
return mode;
}
{
int dpll;
if (HAS_PCH_SPLIT(dev))
return;
if (!dev_priv->lvds_downclock_avail)
return;
DRM_DEBUG_DRIVER("upclocking LVDS\n");
if (dpll & DISPLAY_RATE_SELECT_FPA1)
DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
}
}
{
if (HAS_PCH_SPLIT(dev))
return;
if (!dev_priv->lvds_downclock_avail)
return;
/*
* Since this is called by a timer, we should never get here in
* the manual case.
*/
int dpll;
DRM_DEBUG_DRIVER("downclocking LVDS\n");
if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
}
}
{
}
{
if (!i915_powersave)
return;
continue;
}
}
struct intel_ring_buffer *ring)
{
if (!i915_powersave)
return;
continue;
continue;
}
}
{
unsigned long flags;
if (work) {
}
(INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)));
}
{
}
{
unsigned long flags;
/* Ignore early vblank irqs */
if (intel_crtc == NULL)
return;
return;
}
}
}
{
}
{
}
{
unsigned long flags;
/* NB: An MMIO update of the plane base pointer will also
* generate a page-flip completion irq, i.e. every modeset
* is also accompanied by a spurious intel_prepare_page_flip().
*/
if (intel_crtc->unpin_work)
}
{
/* Ensure that the work item is consistent when activating it ... */
/* and that it is marked active as soon as the irq could fire. */
}
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
int ret;
if (ret)
goto err;
if (ret)
goto err_unpin;
/* Can't queue multiple flips, so wait for the previous
* one to finish before executing the next.
*/
if (intel_crtc->plane)
else
return 0;
err:
return ret;
}
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
int ret;
if (ret)
goto err;
if (ret)
goto err_unpin;
if (intel_crtc->plane)
else
return 0;
err:
return ret;
}
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
int ret;
if (ret)
goto err;
if (ret)
goto err_unpin;
/* i965+ uses the linear or tiled offsets from the
* Display Registers (which do not change across a page-flip)
* so we need only reprogram the base address.
*/
obj->tiling_mode);
/* XXX Enabling the panel-fitter across page-flip is so far
* untested on non-native modes, so ignore it for now.
* pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
*/
pf = 0;
return 0;
err:
return ret;
}
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
int ret;
if (ret)
goto err;
if (ret)
goto err_unpin;
/* Contrary to the suggestions in the documentation,
* "Enable Panel Fitter" does not seem to be required when page
* flipping with a non-native mode, and worse causes a normal
* modeset to fail.
* pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
*/
pf = 0;
return 0;
err:
return ret;
}
/*
* On gen7 we currently use the blit ring because (in early silicon at least)
* the render ring doesn't give us interrpts for page flip completion, which
* means clients will hang after the first flip is queued. Fortunately the
* blit ring generates interrupts properly, so use it instead.
*/
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
int ret;
if (ret)
goto err;
switch(intel_crtc->plane) {
case PLANE_A:
break;
case PLANE_B:
break;
case PLANE_C:
break;
default:
DRM_ERROR("unknown plane in flip command\n");
goto err_unpin;
}
if (ret)
goto err_unpin;
return 0;
err:
return ret;
}
struct drm_framebuffer *fb,
struct drm_i915_gem_object *obj)
{
return -ENODEV;
}
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event)
{
unsigned long flags;
int ret;
/* Can't change pixel format via MI display flips. */
return -EINVAL;
/*
* Note that pitch changes could also affect these register.
*/
return -EINVAL;
return -ENOMEM;
if (ret)
goto free_work;
/* We borrow the event spin lock for protecting unpin_work */
if (intel_crtc->unpin_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
return -EBUSY;
}
/* Reference the objects for the scheduled work. */
work->enable_stall_check = true;
if (ret)
goto cleanup_pending;
return 0;
return ret;
}
};
{
break;
crtc_mask <<= 1;
}
return true;
return false;
}
/**
* intel_modeset_update_staged_output_state
*
* Updates the staged output configuration state, e.g. after we've read out the
* current hw state.
*/
{
}
}
}
/**
* intel_modeset_commit_output_state
*
* This function copies the stage display pipe configuration to the real one.
*/
{
}
}
}
static void
struct intel_crtc_config *pipe_config)
{
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
/* Don't use an invalid EDID bpc value */
DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
}
/* Clamp bpp to 8 on screens without EDID 1.4 */
DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
bpp);
}
}
static int
struct drm_framebuffer *fb,
struct intel_crtc_config *pipe_config)
{
int bpp;
switch (fb->pixel_format) {
case DRM_FORMAT_C8:
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
/* checked in intel_framebuffer_init already */
return -EINVAL;
case DRM_FORMAT_RGB565:
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
/* checked in intel_framebuffer_init already */
return -EINVAL;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
/* checked in intel_framebuffer_init already */
return -EINVAL;
break;
/* TODO: gen4+ supports 16 bpc floating point, too. */
default:
DRM_DEBUG_KMS("unsupported depth\n");
return -EINVAL;
}
/* Clamp display bpp to EDID value */
if (!connector->new_encoder ||
continue;
}
return bpp;
}
struct intel_crtc_config *pipe_config,
const char *context)
{
DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
DRM_DEBUG_KMS("requested mode:\n");
DRM_DEBUG_KMS("adjusted mode:\n");
DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
}
{
int num_encoders = 0;
bool uncloneable_encoders = false;
continue;
num_encoders++;
uncloneable_encoders = true;
}
}
static struct intel_crtc_config *
struct drm_framebuffer *fb,
struct drm_display_mode *mode)
{
bool retry = true;
if (!check_encoder_cloning(crtc)) {
DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
return NULL;
}
if (!pipe_config)
return NULL;
/* Compute a starting value for pipe_config->pipe_bpp taking the source
* plane pixel format and any sink constraints into account. Returns the
* source plane bpp so that dithering can be selected on mismatches
* after encoders and crtc also have had their say. */
fb, pipe_config);
if (plane_bpp < 0)
goto fail;
/* Ensure the port clock defaults are reset when retrying. */
pipe_config->port_clock = 0;
/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
*/
continue;
if (encoder->compute_config) {
DRM_DEBUG_KMS("Encoder config failure\n");
goto fail;
}
continue;
}
&pipe_config->adjusted_mode))) {
DRM_DEBUG_KMS("Encoder fixup failed\n");
goto fail;
}
}
/* Set default port clock if not overwritten by the encoder. Needs to be
* done afterwards in case the encoder adjusts the mode. */
if (!pipe_config->port_clock)
if (ret < 0) {
DRM_DEBUG_KMS("CRTC fixup failed\n");
goto fail;
}
if (!retry) {
DRM_ERROR("loop in pipe configuration computation");
goto fail;
}
DRM_DEBUG_KMS("CRTC bw constrained, retrying\n");
retry = false;
goto encoder_retry;
}
DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
return pipe_config;
fail:
return NULL;
}
/* Computes which crtcs are affected and sets the relevant bits in the mask. For
* simplicity we use the crtc's pipe number (because it's easier to obtain). */
static void
unsigned *prepare_pipes, unsigned *disable_pipes)
{
/* Check which crtcs have changed outputs connected to them, these need
* to be part of the prepare_pipes mask. We don't (yet) support global
* modeset across multiple crtcs, so modeset_pipes will only have one
* bit set at most. */
continue;
}
if (connector->new_encoder)
*prepare_pipes |=
}
continue;
}
}
/* Check for any pipes that will be fully disabled ... */
bool used = false;
/* Don't try to disable disabled crtcs. */
continue;
used = true;
}
if (!used)
}
/* set_mode is also used to update properties on life display pipes. */
/*
* For simplicity do a full modeset on any pipe where the output routing
* changed. We could be more clever, but that would require us to be
* more careful with calling the relevant encoder->mode_set functions.
*/
if (*prepare_pipes)
/* ... and mask these out. */
*modeset_pipes &= ~(*disable_pipes);
*prepare_pipes &= ~(*disable_pipes);
/*
* HACK: We don't (yet) fully support global modesets. intel_set_config
* obies this rule, but the modeset restore mode of
* intel_modeset_setup_hw_state does not.
*/
DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
}
{
return true;
return false;
}
static void
{
continue;
intel_encoder->connectors_active = false;
}
/* Update computed state. */
}
continue;
intel_encoder->connectors_active = true;
}
}
}
static bool
struct intel_crtc_config *current_config,
struct intel_crtc_config *pipe_config)
{
"(expected 0x%08x, found 0x%08x)\n", \
current_config->name, \
pipe_config->name); \
return false; \
}
"(expected %i, found %i)\n", \
current_config->name, \
pipe_config->name); \
return false; \
}
"(expected %i, found %i)\n", \
return false; \
}
if (!HAS_PCH_SPLIT(dev))
}
/* pfit ratios are autocomputed by the hw on gen4+ */
return true;
}
static void
{
* ->get_hw_state callbacks. */
DRM_ERROR("connector's staged encoder doesn't match current encoder\n");
}
}
static void
{
bool enabled = false;
bool active = false;
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
DRM_ERROR("encoder's stage crtc doesn't match current crtc\n");
DRM_ERROR("encoder's active_connectors set, but no crtc\n");
continue;
enabled = true;
active = true;
}
DRM_ERROR("encoder's enabled state mismatch "
"(expected %i, found %i)\n",
DRM_ERROR("active encoder with no crtc\n");
DRM_ERROR("encoder's computed active state doesn't match tracked active state "
DRM_ERROR("encoder's hw state doesn't match sw tracking "
"(expected %i, found %i)\n",
continue;
DRM_ERROR("active encoder's pipe doesn't match"
"(expected %i, found %i)\n",
tracked_pipe, pipe);
}
}
static void
{
bool enabled = false;
bool active = false;
DRM_DEBUG_KMS("[CRTC:%d]\n",
DRM_ERROR("active crtc, but not enabled in sw tracking\n");
continue;
enabled = true;
if (encoder->connectors_active)
active = true;
}
DRM_ERROR("crtc's computed active state doesn't match tracked active state "
DRM_ERROR("crtc's computed enabled state doesn't match tracked enabled state "
&pipe_config);
/* hw state is inconsistent with the pipe A quirk */
continue;
if (encoder->get_config &&
}
DRM_ERROR("crtc active state doesn't match with hw state "
if (active &&
DRM_DEBUG_KMS("pipe state doesn't match!\n");
"[hw state]");
"[sw state]");
}
}
}
static void
{
int i;
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
bool active;
DRM_DEBUG_KMS("more active pll users than references: %i vs %i\n",
DRM_DEBUG_KMS("pll in active use but not on in sw tracking\n");
DRM_DEBUG_KMS("pll in on but not on in use in sw tracking\n");
DRM_DEBUG_KMS("pll on state mismatch (expected %i, found %i)\n",
active_crtcs++;
}
DRM_DEBUG_KMS("pll active crtcs mismatch (expected %i, found %i)\n",
DRM_DEBUG_KMS("pll enabled crtcs mismatch (expected %i, found %i)\n",
sizeof(dpll_hw_state)))
DRM_ERROR("pll hw state mismatch\n");
}
}
void
{
}
struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *fb)
{
int ret = 0;
if (!saved_mode)
return -ENOMEM;
/* Hack: Because we don't (yet) support global modeset on multiple
* crtcs, we don't keep track of the new mode for more than one crtc.
* Hence simply check whether any bit is set in modeset_pipes in all the
* pieces of code that are not yet converted to deal with mutliple crtcs
* changing their mode at the same time. */
if (modeset_pipes) {
if (!(pipe_config)) {
pipe_config = NULL;
goto out;
}
"[modeset]");
}
}
/* crtc->mode is already used by the ->mode_set callbacks, hence we need
* to set it here already despite that we pass it down the callchain.
*/
if (modeset_pipes) {
* config. */
}
/* Only after disabling all output pipelines that will be changed can we
* update the the output configuration. */
/* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL.
*/
x, y, fb);
if (ret)
goto done;
}
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
if (modeset_pipes) {
/* Store real post-adjustment hardware mode. */
/* Calculate and store various constants which
* are later needed by vblank and swap-completion
* timestamping. They are derived from true hwmode.
*/
}
/* FIXME: add subpixel order */
done:
}
out:
if (pipe_config)
return ret;
}
struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *fb)
{
int ret;
if (ret == 0)
return ret;
}
{
}
{
if (!config)
return;
kfree(config->save_connector_encoders, dev->mode_config.num_connector * sizeof(struct drm_encoder *));
}
struct intel_set_config *config)
{
int count;
sizeof(struct drm_crtc *), GFP_KERNEL);
if (!config->save_encoder_crtcs)
return -ENOMEM;
sizeof(struct drm_encoder *), GFP_KERNEL);
if (!config->save_connector_encoders)
return -ENOMEM;
/* Copy data. Note that driver private data is not affected.
* Should anything bad happen only the expected state is
* restored, not the drivers personal bookkeeping.
*/
count = 0;
}
count = 0;
}
return 0;
}
struct intel_set_config *config)
{
int count;
count = 0;
}
count = 0;
list_for_each_entry(connector, struct intel_connector, &dev->mode_config.connector_list, base.head) {
}
}
static bool
{
int i;
if (set->num_connectors == 0)
return false;
return false;
for (i = 0; i < set->num_connectors; i++)
return true;
return false;
}
static void
struct intel_set_config *config)
{
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (is_crtc_connector_off(set)) {
config->mode_changed = true;
/* If we have no fb then treat it as a full mode set */
DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
config->mode_changed = true;
config->mode_changed = true;
config->mode_changed = true;
} else {
config->fb_changed = true;
}
}
config->fb_changed = true;
DRM_DEBUG_KMS("modes are different, full mode set\n");
config->mode_changed = true;
}
}
static int
struct drm_mode_set *set,
struct intel_set_config *config)
{
/* LINTED */
/* The upper layers ensure that we either disabl a crtc or have a list
* of connectors. For paranoia, double-check this. */
count = 0;
/* Otherwise traverse passed in connector list and get encoders
* for them. */
break;
}
}
/* If we disable the crtc, disable all its connectors. Also, if
* the connector is on the changing crtc but not on the new
* connector list, disable it. */
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
}
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
config->mode_changed = true;
}
}
/* connector->new_encoder is now updated for all connectors. */
/* Update crtc of enabled connectors. */
count = 0;
if (!connector->new_encoder)
continue;
}
/* Make sure the new CRTC will work with the encoder */
new_crtc)) {
return -EINVAL;
}
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
}
/* Check for any encoders that needs to be disabled. */
goto next_encoder;
}
}
/* Only now check for crtc changes so we don't miss encoders
* that will be disabled. */
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
config->mode_changed = true;
}
}
/* Now we've also updated encoder->new_crtc for all encoders. */
return 0;
}
{
int ret;
/* Enforce sane interface api - has been abused by the fb helper. */
DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
} else {
}
if (!config)
goto out_config;
if (ret)
goto out_config;
/* Compute whether we need a full modeset, only an fb base update or no
* change at all. In the future we might also check whether only the
* mode changed, e.g. for LVDS where we only change the panel fitter in
* such cases. */
if (ret)
goto fail;
if (config->mode_changed) {
DRM_DEBUG_KMS("fb changed without set->mode");
goto fail;
}
} else if (config->fb_changed) {
}
if (ret) {
DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
fail:
/* Try to restore the config */
if (config->mode_changed &&
DRM_ERROR("failed to restore config after modeset failure\n");
}
return ret;
}
};
{
}
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
return val & DPLL_VCO_ENABLE;
}
struct intel_shared_dpll *pll)
{
/* PCH refclock must be enabled first */
val |= DPLL_VCO_ENABLE;
udelay(200);
}
struct intel_shared_dpll *pll)
{
/* Make sure no transcoder isn't still depending on us. */
}
val &= ~DPLL_VCO_ENABLE;
udelay(200);
}
static char *ibx_pch_dpll_names[] = {
"PCH DPLL A",
"PCH DPLL B",
};
{
int i;
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
}
}
{
else
dev_priv->num_shared_dpll = 0;
DRM_DEBUG_KMS("%i shared PLLs initialized\n",
}
{
int i;
intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
if (intel_crtc == NULL)
return;
for (i = 0; i < 256; i++) {
}
/* Swap pipes & planes for FBC on pre-965 */
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
}
}
/* LINTED */
{
return -ENODEV;
if (!drmmode_obj) {
DRM_ERROR("no such CRTC id\n");
return -EINVAL;
}
return 0;
}
{
int index_mask = 0;
int entry = 0;
if (encoder == source_encoder)
/* Intel hw has only one MUX where enocoders could be cloned. */
entry++;
}
return index_mask;
}
{
return false;
return false;
return false;
return true;
}
{
bool dpd_is_edp = false;
int found;
/* Haswell uses DDI functions to detect digital outputs */
/* DDI A only supports eDP */
if (found)
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
* register */
if (found & SFUSE_STRAP_DDIB_DETECTED)
if (found & SFUSE_STRAP_DDIC_DETECTED)
if (found & SFUSE_STRAP_DDID_DETECTED)
} else if (HAS_PCH_SPLIT(dev)) {
int found;
/* PCH SDVOB multiplex with HDMIB */
if (!found)
}
} else if (IS_VALLEYVIEW(dev)) {
/* Check for built-in panel first. Shares lanes with HDMI on SDVOC */
PORT_B);
}
} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
bool found = false;
DRM_DEBUG_KMS("probing SDVOB\n");
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
}
}
/* Before G4X SDVOC doesn't have its own detect register */
DRM_DEBUG_KMS("probing SDVOC\n");
}
if (SUPPORTS_INTEGRATED_HDMI(dev)) {
DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
}
if (SUPPORTS_INTEGRATED_DP(dev))
}
if (SUPPORTS_INTEGRATED_DP(dev) &&
if (SUPPORTS_TV(dev))
}
}
{
}
unsigned int *handle)
{
}
};
struct intel_framebuffer *intel_fb,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj)
{
int pitch_limit;
int ret;
DRM_DEBUG("hardware does not support tiling Y\n");
return -EINVAL;
}
DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
return -EINVAL;
}
if (obj->tiling_mode)
else
if (obj->tiling_mode)
else
} else
/* XXX DSPC is limited to 4k tiled */
DRM_DEBUG("%s pitch (%d) must be at less than %d\n",
return -EINVAL;
}
DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
return -EINVAL;
}
/* Reject formats not supported by any plane early. */
switch (mode_cmd->pixel_format) {
case DRM_FORMAT_C8:
case DRM_FORMAT_RGB565:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
DRM_DEBUG("unsupported pixel format: %s\n",
return -EINVAL;
}
break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
DRM_DEBUG("unsupported pixel format: %s\n",
return -EINVAL;
}
break;
case DRM_FORMAT_YUYV:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_VYUY:
DRM_DEBUG("unsupported pixel format: %s\n",
return -EINVAL;
}
break;
default:
DRM_DEBUG("unsupported pixel format: %s\n",
return -EINVAL;
}
return -EINVAL;
if (ret) {
return ret;
}
return 0;
}
static struct drm_framebuffer *
struct drm_mode_fb_cmd2 *mode_cmd)
{
return (NULL);
}
};
/* Set up chip specific display functions */
{
else if (IS_VALLEYVIEW(dev))
else if (IS_PINEVIEW(dev))
else
} else if (HAS_PCH_SPLIT(dev)) {
} else if (IS_VALLEYVIEW(dev)) {
} else {
}
/* Returns the core display clock speed */
if (IS_VALLEYVIEW(dev))
else /* 852, 830 */
if (HAS_PCH_SPLIT(dev)) {
} else if (IS_IVYBRIDGE(dev)) {
/* FIXME: detect B0+ stepping and use auto training */
} else if (IS_HASWELL(dev)) {
}
}
/* Default just returns -ENODEV to indicate unsupported */
case 2:
break;
case 3:
break;
case 4:
case 5:
break;
case 6:
break;
case 7:
break;
}
}
/*
* Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend,
* resume, or other times. This quirk makes sure that's the case for
* affected systems.
*/
{
DRM_INFO("applying pipe a force quirk\n");
}
/*
* Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
*/
{
DRM_INFO("applying lvds SSC disable quirk\n");
}
/*
* A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight
* brightness value
*/
{
DRM_INFO("applying inverted panel brightness quirk\n");
}
#if 0
/*
* Some machines (Dell XPS13) suffer broken backlight controls if
* BLM_PCH_PWM_ENABLE is set.
*/
{
DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
}
struct intel_quirk {
int device;
int subsystem_vendor;
int subsystem_device;
};
struct intel_dmi_quirk {
const struct dmi_system_id (*dmi_id_list)[];
};
{
return 1;
}
static const struct intel_dmi_quirk intel_dmi_quirks[] = {
{
.dmi_id_list = &(const struct dmi_system_id[]) {
{
.ident = "NCR Corporation",
},
},
{ } /* terminating entry */
},
},
};
static struct intel_quirk intel_quirks[] = {
/* HP Mini needs pipe A force quirk (LP: #322104) */
/* Toshiba Protege R-205, S-209 needs pipe A force quirk */
/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
/* 830/845 need to leave pipe A & dpll A up */
/* Lenovo U160 cannot use SSC on LVDS */
/* Sony Vaio Y cannot use SSC on LVDS */
/* Acer Aspire 5734Z must invert backlight brightness */
/* Acer Aspire 4736Z */
/* Dell XPS13 HD Sandy Bridge */
/* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
};
{
int i;
for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
struct intel_quirk *q = &intel_quirks[i];
(d->subsystem_vendor == q->subsystem_vendor ||
q->subsystem_vendor == PCI_ANY_ID) &&
(d->subsystem_device == q->subsystem_device ||
q->subsystem_device == PCI_ANY_ID))
}
for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
}
}
#endif
/* Disable the VGA plane that we never use */
{
udelay(300);
}
{
}
{
}
{
int i, j, ret;
/* OSOL_I915 intel_init_quirks(dev); */
return;
} else {
}
DRM_DEBUG_KMS("%d display pipe%s available.\n",
intel_crtc_init(dev, i);
if (ret)
DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
}
}
/* Just disable it once at startup */
/* Just in case the BIOS is doing something questionable. */
}
static void
{
}
{
/* We can't just switch on the pipe A, we need to set things up with a
* proper mode and output configuration. As a gross hack, enable pipe A
* by enabling the load detect pipe once. */
break;
}
}
if (!crt)
return;
}
static bool
{
return true;
if ((val & DISPLAY_PLANE_ENABLE) &&
return false;
return true;
}
{
/* Clear any frame start delays used for debugging left by the BIOS */
/* We need to sanitize the plane -> pipe mapping first because this will
* disable the crtc (and hence change the state) if it is wrong. Note
* that gen4+ has a fixed plane -> pipe mapping. */
bool plane;
DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
/* Pipe has the wrong plane attached and the plane is active.
* Temporarily change the plane mapping and disable everything
* ... */
/* ... and break all links. */
continue;
}
}
/* BIOS forgot to enable pipe A, this mostly happens after
* resume. Force-enable the pipe to fix this, the update_dpms
* call below we restore the pipe to the right state, but leave
* the required bits on. */
}
/* Adjust the state of the output pipe according to whether we
* have active connectors/encoders. */
/* This can happen either due to bugs in the get_hw_state
* functions or because the pipe is force-enabled due to the
* pipe A quirk. */
DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
/* Because we only establish the connector -> encoder ->
* crtc links if something is active, this means the
* crtc is now deactivated. Break the links. connector
* -> encoder links are only establish when things are
* actually up, hence no need to break them. */
}
}
}
{
/* We need to check both for a crtc link (meaning that the
* encoder is active and trying to read from a pipe) and the
* pipe itself being active. */
DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
/* Connector is active, but has no active pipe. This is
* fallout from our resume register restoring. Disable
* the encoder manually again. */
DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
}
* a bug in one of the get_hw_state functions. Or someplace else
* in our code, like the register restore mess on resume. Clamp
* things to off as a safer default. */
continue;
}
}
/* Enabled encoders without active connectors will be fixed in
* the crtc fixup. */
}
{
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
}
}
{
int i;
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
}
/* FIXME: Smash this into the new shared dpll infrastructure. */
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
}
DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
}
pipe = 0;
if (encoder->get_config)
} else {
}
encoder->connectors_active = false;
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
pipe);
}
} else {
}
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
}
}
/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
* and i915 state tracking structures. */
bool force_restore)
{
int i;
/* HW state is read out, now we need to sanitize this mess. */
}
}
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
continue;
}
if (force_restore) {
/*
* We need to use raw interfaces for restoring state to avoid
* checking (bogus) intermediate states.
*/
}
} else {
}
}
{
intel_modeset_setup_hw_state(dev, false);
}
{
/* LINTED */
/*
* Interrupts and polling as the first thing to avoid creating havoc.
* Too much stuff here (turning of rps, connectors, ...) would
* experience fancy races otherwise.
*/
/* OSOL_I915 cancel_work_sync(&dev_priv->hotplug_work); */
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
* poll handlers. Hence disable polling after hpd handling is shut down.
*/
/* Skip inactive CRTCs */
continue;
}
/* flush any delayed tasks or pending work */
/* OSOL_I915 flush_scheduled_work(); */
/* destroy backlight, if any, before the connectors */
}
/* current intel driver doesn't take advantage of encoders
always give back the encoder for the connector
*/
{
}
struct intel_encoder *encoder)
{
}
/*
* set vga decode state - true == enable VGA decode
*/
{
if (state)
else
return 0;
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
struct intel_display_error_state {
int num_transcoders;
struct intel_cursor_error_state {
struct intel_pipe_error_state {
struct intel_plane_error_state {
struct intel_transcoder_error_state {
};
struct intel_display_error_state *
{
};
int i;
return NULL;
return NULL;
if (HAS_POWER_WELL(dev))
for_each_pipe(i) {
} else {
}
}
}
}
for (i = 0; i < error->num_transcoders; i++) {
}
/* In the code above we read the registers without checking if the power
* well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to
* prevent the next I915_WRITE from detecting it and printing an error
* message. */
if (HAS_POWER_WELL(dev))
return error;
}
void
struct drm_device *dev,
struct intel_display_error_state *error)
{
int i;
if (!error)
return;
if (HAS_POWER_WELL(dev))
err_printf(m, "PWR_WELL_CTL2: %08x\n",
for_each_pipe(i) {
err_printf(m, "Pipe [%d]:\n", i);
err_printf(m, "Plane [%d]:\n", i);
}
}
err_printf(m, "Cursor [%d]:\n", i);
}
for (i = 0; i < error->num_transcoders; i++) {
err_printf(m, " CPU transcoder: %c\n",
+ }
}
#endif