DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/*
|
|
|
|
* Copyright © 2006-2007 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,
|
|
|
|
* 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 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>
|
|
|
|
*/
|
|
|
|
|
2012-04-01 19:38:50 +08:00
|
|
|
#include <linux/dmi.h>
|
2009-09-11 06:28:03 +08:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/input.h>
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
#include <linux/i2c.h>
|
2009-06-26 11:23:55 +08:00
|
|
|
#include <linux/kernel.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2010-08-14 06:11:26 +08:00
|
|
|
#include <linux/vgaarb.h>
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
#include <drm/drm_edid.h>
|
2012-10-03 01:01:07 +08:00
|
|
|
#include <drm/drmP.h>
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
#include "intel_drv.h"
|
2012-10-03 01:01:07 +08:00
|
|
|
#include <drm/i915_drm.h>
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
#include "i915_drv.h"
|
2010-07-02 07:48:37 +08:00
|
|
|
#include "i915_trace.h"
|
2012-10-03 01:01:07 +08:00
|
|
|
#include <drm/drm_dp_helper.h>
|
|
|
|
#include <drm/drm_crtc_helper.h>
|
2011-11-17 14:24:52 +08:00
|
|
|
#include <linux/dma_remapping.h>
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
|
2010-08-21 03:40:52 +08:00
|
|
|
static void intel_increase_pllclock(struct drm_crtc *crtc);
|
2010-09-13 20:54:26 +08:00
|
|
|
static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
typedef struct {
|
2011-08-17 03:34:10 +08:00
|
|
|
int min, max;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} intel_range_t;
|
|
|
|
|
|
|
|
typedef struct {
|
2011-08-17 03:34:10 +08:00
|
|
|
int dot_limit;
|
|
|
|
int p2_slow, p2_fast;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} intel_p2_t;
|
|
|
|
|
|
|
|
#define INTEL_P2_NUM 2
|
2009-03-18 20:13:27 +08:00
|
|
|
typedef struct intel_limit intel_limit_t;
|
|
|
|
struct intel_limit {
|
2011-08-17 03:34:10 +08:00
|
|
|
intel_range_t dot, vco, n, m, m1, m2, p, p1;
|
|
|
|
intel_p2_t p2;
|
2013-03-01 01:19:44 +08:00
|
|
|
/**
|
|
|
|
* find_pll() - Find the best values for the PLL
|
|
|
|
* @limit: limits for the PLL
|
|
|
|
* @crtc: current CRTC
|
|
|
|
* @target: target frequency in kHz
|
|
|
|
* @refclk: reference clock frequency in kHz
|
|
|
|
* @match_clock: if provided, @best_clock P divider must
|
|
|
|
* match the P divider from @match_clock
|
|
|
|
* used for LVDS downclocking
|
|
|
|
* @best_clock: best PLL values found
|
|
|
|
*
|
|
|
|
* Returns true on success, false on failure.
|
|
|
|
*/
|
|
|
|
bool (*find_pll)(const intel_limit_t *limit,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
int target, int refclk,
|
|
|
|
intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock);
|
2009-03-18 20:13:27 +08:00
|
|
|
};
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-07-08 05:06:43 +08:00
|
|
|
/* FDI */
|
|
|
|
#define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */
|
|
|
|
|
2012-10-21 02:57:43 +08:00
|
|
|
int
|
|
|
|
intel_pch_rawclk(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
WARN_ON(!HAS_PCH_SPLIT(dev));
|
|
|
|
|
|
|
|
return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
|
|
|
|
}
|
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
static bool
|
|
|
|
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
2012-01-11 07:09:36 +08:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock);
|
2009-03-18 20:13:27 +08:00
|
|
|
static bool
|
|
|
|
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
2012-01-11 07:09:36 +08:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-06-16 02:55:13 +08:00
|
|
|
static bool
|
|
|
|
intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock);
|
|
|
|
|
2010-09-08 03:54:59 +08:00
|
|
|
static inline u32 /* units of 100MHz */
|
|
|
|
intel_fdi_link_freq(struct drm_device *dev)
|
|
|
|
{
|
2010-10-13 16:59:17 +08:00
|
|
|
if (IS_GEN5(dev)) {
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2;
|
|
|
|
} else
|
|
|
|
return 27;
|
2010-09-08 03:54:59 +08:00
|
|
|
}
|
|
|
|
|
2009-06-06 10:22:17 +08:00
|
|
|
static const intel_limit_t intel_limits_i8xx_dvo = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 930000, .max = 1400000 },
|
|
|
|
.n = { .min = 3, .max = 16 },
|
|
|
|
.m = { .min = 96, .max = 140 },
|
|
|
|
.m1 = { .min = 18, .max = 26 },
|
|
|
|
.m2 = { .min = 6, .max = 16 },
|
|
|
|
.p = { .min = 4, .max = 128 },
|
|
|
|
.p1 = { .min = 2, .max = 33 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
.p2_slow = 4, .p2_fast = 2 },
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_i8xx_lvds = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 930000, .max = 1400000 },
|
|
|
|
.n = { .min = 3, .max = 16 },
|
|
|
|
.m = { .min = 96, .max = 140 },
|
|
|
|
.m1 = { .min = 18, .max = 26 },
|
|
|
|
.m2 = { .min = 6, .max = 16 },
|
|
|
|
.p = { .min = 4, .max = 128 },
|
|
|
|
.p1 = { .min = 1, .max = 6 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
.p2_slow = 14, .p2_fast = 7 },
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
2011-03-31 04:01:10 +08:00
|
|
|
|
2009-06-06 10:22:17 +08:00
|
|
|
static const intel_limit_t intel_limits_i9xx_sdvo = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 20000, .max = 400000 },
|
|
|
|
.vco = { .min = 1400000, .max = 2800000 },
|
|
|
|
.n = { .min = 1, .max = 6 },
|
|
|
|
.m = { .min = 70, .max = 120 },
|
2013-02-14 05:20:22 +08:00
|
|
|
.m1 = { .min = 8, .max = 18 },
|
|
|
|
.m2 = { .min = 3, .max = 7 },
|
2011-08-17 03:34:10 +08:00
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 200000,
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_i9xx_lvds = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 20000, .max = 400000 },
|
|
|
|
.vco = { .min = 1400000, .max = 2800000 },
|
|
|
|
.n = { .min = 1, .max = 6 },
|
|
|
|
.m = { .min = 70, .max = 120 },
|
2013-02-14 05:20:21 +08:00
|
|
|
.m1 = { .min = 8, .max = 18 },
|
|
|
|
.m2 = { .min = 3, .max = 7 },
|
2011-08-17 03:34:10 +08:00
|
|
|
.p = { .min = 7, .max = 98 },
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 112000,
|
|
|
|
.p2_slow = 14, .p2_fast = 7 },
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
2011-03-31 04:01:10 +08:00
|
|
|
|
2009-06-06 10:22:17 +08:00
|
|
|
static const intel_limit_t intel_limits_g4x_sdvo = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 270000 },
|
|
|
|
.vco = { .min = 1750000, .max = 3500000},
|
|
|
|
.n = { .min = 1, .max = 4 },
|
|
|
|
.m = { .min = 104, .max = 138 },
|
|
|
|
.m1 = { .min = 17, .max = 23 },
|
|
|
|
.m2 = { .min = 5, .max = 11 },
|
|
|
|
.p = { .min = 10, .max = 30 },
|
|
|
|
.p1 = { .min = 1, .max = 3},
|
|
|
|
.p2 = { .dot_limit = 270000,
|
|
|
|
.p2_slow = 10,
|
|
|
|
.p2_fast = 10
|
2009-03-18 20:13:23 +08:00
|
|
|
},
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_hdmi = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 22000, .max = 400000 },
|
|
|
|
.vco = { .min = 1750000, .max = 3500000},
|
|
|
|
.n = { .min = 1, .max = 4 },
|
|
|
|
.m = { .min = 104, .max = 138 },
|
|
|
|
.m1 = { .min = 16, .max = 23 },
|
|
|
|
.m2 = { .min = 5, .max = 11 },
|
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
.p1 = { .min = 1, .max = 8},
|
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 20000, .max = 115000 },
|
|
|
|
.vco = { .min = 1750000, .max = 3500000 },
|
|
|
|
.n = { .min = 1, .max = 3 },
|
|
|
|
.m = { .min = 104, .max = 138 },
|
|
|
|
.m1 = { .min = 17, .max = 23 },
|
|
|
|
.m2 = { .min = 5, .max = 11 },
|
|
|
|
.p = { .min = 28, .max = 112 },
|
|
|
|
.p1 = { .min = 2, .max = 8 },
|
|
|
|
.p2 = { .dot_limit = 0,
|
|
|
|
.p2_slow = 14, .p2_fast = 14
|
2009-03-18 20:13:23 +08:00
|
|
|
},
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 80000, .max = 224000 },
|
|
|
|
.vco = { .min = 1750000, .max = 3500000 },
|
|
|
|
.n = { .min = 1, .max = 3 },
|
|
|
|
.m = { .min = 104, .max = 138 },
|
|
|
|
.m1 = { .min = 17, .max = 23 },
|
|
|
|
.m2 = { .min = 5, .max = 11 },
|
|
|
|
.p = { .min = 14, .max = 42 },
|
|
|
|
.p1 = { .min = 2, .max = 6 },
|
|
|
|
.p2 = { .dot_limit = 0,
|
|
|
|
.p2_slow = 7, .p2_fast = 7
|
2009-03-18 20:13:23 +08:00
|
|
|
},
|
2009-03-18 20:13:27 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
2009-12-04 06:14:42 +08:00
|
|
|
static const intel_limit_t intel_limits_pineview_sdvo = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 20000, .max = 400000},
|
|
|
|
.vco = { .min = 1700000, .max = 3500000 },
|
2011-03-31 04:01:10 +08:00
|
|
|
/* Pineview's Ncounter is a ring counter */
|
2011-08-17 03:34:10 +08:00
|
|
|
.n = { .min = 3, .max = 6 },
|
|
|
|
.m = { .min = 2, .max = 256 },
|
2011-03-31 04:01:10 +08:00
|
|
|
/* Pineview only has one combined m divider, which we treat as m2. */
|
2011-08-17 03:34:10 +08:00
|
|
|
.m1 = { .min = 0, .max = 0 },
|
|
|
|
.m2 = { .min = 0, .max = 254 },
|
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 200000,
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-04-03 15:24:43 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
2009-12-04 06:14:42 +08:00
|
|
|
static const intel_limit_t intel_limits_pineview_lvds = {
|
2011-08-17 03:34:10 +08:00
|
|
|
.dot = { .min = 20000, .max = 400000 },
|
|
|
|
.vco = { .min = 1700000, .max = 3500000 },
|
|
|
|
.n = { .min = 3, .max = 6 },
|
|
|
|
.m = { .min = 2, .max = 256 },
|
|
|
|
.m1 = { .min = 0, .max = 0 },
|
|
|
|
.m2 = { .min = 0, .max = 254 },
|
|
|
|
.p = { .min = 7, .max = 112 },
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 112000,
|
|
|
|
.p2_slow = 14, .p2_fast = 14 },
|
2009-04-03 15:24:43 +08:00
|
|
|
.find_pll = intel_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
2011-03-31 04:01:10 +08:00
|
|
|
/* Ironlake / Sandybridge
|
|
|
|
*
|
|
|
|
* We calculate clock using (register_value + 2) for N/M1/M2, so here
|
|
|
|
* the range value for them is (actual_value - 2).
|
|
|
|
*/
|
2010-02-05 09:14:17 +08:00
|
|
|
static const intel_limit_t intel_limits_ironlake_dac = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 1760000, .max = 3510000 },
|
|
|
|
.n = { .min = 1, .max = 5 },
|
|
|
|
.m = { .min = 79, .max = 127 },
|
|
|
|
.m1 = { .min = 12, .max = 22 },
|
|
|
|
.m2 = { .min = 5, .max = 9 },
|
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-12-31 16:06:04 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
2009-06-06 10:22:17 +08:00
|
|
|
};
|
|
|
|
|
2010-02-05 09:14:17 +08:00
|
|
|
static const intel_limit_t intel_limits_ironlake_single_lvds = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 1760000, .max = 3510000 },
|
|
|
|
.n = { .min = 1, .max = 3 },
|
|
|
|
.m = { .min = 79, .max = 118 },
|
|
|
|
.m1 = { .min = 12, .max = 22 },
|
|
|
|
.m2 = { .min = 5, .max = 9 },
|
|
|
|
.p = { .min = 28, .max = 112 },
|
|
|
|
.p1 = { .min = 2, .max = 8 },
|
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
.p2_slow = 14, .p2_fast = 14 },
|
2010-02-05 09:14:17 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_ironlake_dual_lvds = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 1760000, .max = 3510000 },
|
|
|
|
.n = { .min = 1, .max = 3 },
|
|
|
|
.m = { .min = 79, .max = 127 },
|
|
|
|
.m1 = { .min = 12, .max = 22 },
|
|
|
|
.m2 = { .min = 5, .max = 9 },
|
|
|
|
.p = { .min = 14, .max = 56 },
|
|
|
|
.p1 = { .min = 2, .max = 8 },
|
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
.p2_slow = 7, .p2_fast = 7 },
|
2010-02-05 09:14:17 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
|
|
|
};
|
|
|
|
|
2011-03-31 04:01:10 +08:00
|
|
|
/* LVDS 100mhz refclk limits. */
|
2010-02-05 09:14:17 +08:00
|
|
|
static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 1760000, .max = 3510000 },
|
|
|
|
.n = { .min = 1, .max = 2 },
|
|
|
|
.m = { .min = 79, .max = 126 },
|
|
|
|
.m1 = { .min = 12, .max = 22 },
|
|
|
|
.m2 = { .min = 5, .max = 9 },
|
|
|
|
.p = { .min = 28, .max = 112 },
|
2011-08-17 03:34:10 +08:00
|
|
|
.p1 = { .min = 2, .max = 8 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
.p2_slow = 14, .p2_fast = 14 },
|
2010-02-05 09:14:17 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
|
2011-03-31 04:01:10 +08:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
|
|
|
.vco = { .min = 1760000, .max = 3510000 },
|
|
|
|
.n = { .min = 1, .max = 3 },
|
|
|
|
.m = { .min = 79, .max = 126 },
|
|
|
|
.m1 = { .min = 12, .max = 22 },
|
|
|
|
.m2 = { .min = 5, .max = 9 },
|
|
|
|
.p = { .min = 14, .max = 42 },
|
2011-08-17 03:34:10 +08:00
|
|
|
.p1 = { .min = 2, .max = 6 },
|
2011-03-31 04:01:10 +08:00
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
.p2_slow = 7, .p2_fast = 7 },
|
2009-12-31 16:06:04 +08:00
|
|
|
.find_pll = intel_g4x_find_best_PLL,
|
|
|
|
};
|
|
|
|
|
2012-06-16 02:55:13 +08:00
|
|
|
static const intel_limit_t intel_limits_vlv_dac = {
|
|
|
|
.dot = { .min = 25000, .max = 270000 },
|
|
|
|
.vco = { .min = 4000000, .max = 6000000 },
|
|
|
|
.n = { .min = 1, .max = 7 },
|
|
|
|
.m = { .min = 22, .max = 450 }, /* guess */
|
|
|
|
.m1 = { .min = 2, .max = 3 },
|
|
|
|
.m2 = { .min = 11, .max = 156 },
|
|
|
|
.p = { .min = 10, .max = 30 },
|
2013-04-19 03:10:43 +08:00
|
|
|
.p1 = { .min = 1, .max = 3 },
|
2012-06-16 02:55:13 +08:00
|
|
|
.p2 = { .dot_limit = 270000,
|
|
|
|
.p2_slow = 2, .p2_fast = 20 },
|
|
|
|
.find_pll = intel_vlv_find_best_pll,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_vlv_hdmi = {
|
2013-04-19 03:10:43 +08:00
|
|
|
.dot = { .min = 25000, .max = 270000 },
|
|
|
|
.vco = { .min = 4000000, .max = 6000000 },
|
2012-06-16 02:55:13 +08:00
|
|
|
.n = { .min = 1, .max = 7 },
|
|
|
|
.m = { .min = 60, .max = 300 }, /* guess */
|
|
|
|
.m1 = { .min = 2, .max = 3 },
|
|
|
|
.m2 = { .min = 11, .max = 156 },
|
|
|
|
.p = { .min = 10, .max = 30 },
|
|
|
|
.p1 = { .min = 2, .max = 3 },
|
|
|
|
.p2 = { .dot_limit = 270000,
|
|
|
|
.p2_slow = 2, .p2_fast = 20 },
|
|
|
|
.find_pll = intel_vlv_find_best_pll,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_vlv_dp = {
|
2012-09-27 21:43:04 +08:00
|
|
|
.dot = { .min = 25000, .max = 270000 },
|
|
|
|
.vco = { .min = 4000000, .max = 6000000 },
|
2012-06-16 02:55:13 +08:00
|
|
|
.n = { .min = 1, .max = 7 },
|
2012-09-27 21:43:04 +08:00
|
|
|
.m = { .min = 22, .max = 450 },
|
2012-06-16 02:55:13 +08:00
|
|
|
.m1 = { .min = 2, .max = 3 },
|
|
|
|
.m2 = { .min = 11, .max = 156 },
|
|
|
|
.p = { .min = 10, .max = 30 },
|
2013-04-19 03:10:43 +08:00
|
|
|
.p1 = { .min = 1, .max = 3 },
|
2012-06-16 02:55:13 +08:00
|
|
|
.p2 = { .dot_limit = 270000,
|
|
|
|
.p2_slow = 2, .p2_fast = 20 },
|
|
|
|
.find_pll = intel_vlv_find_best_pll,
|
|
|
|
};
|
|
|
|
|
2010-12-15 04:04:54 +08:00
|
|
|
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
|
|
|
|
int refclk)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2010-02-05 09:14:17 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2009-06-05 15:38:42 +08:00
|
|
|
const intel_limit_t *limit;
|
2010-02-05 09:14:17 +08:00
|
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
2012-11-27 00:22:09 +08:00
|
|
|
if (intel_is_dual_link_lvds(dev)) {
|
2010-12-15 04:04:54 +08:00
|
|
|
if (refclk == 100000)
|
2010-02-05 09:14:17 +08:00
|
|
|
limit = &intel_limits_ironlake_dual_lvds_100m;
|
|
|
|
else
|
|
|
|
limit = &intel_limits_ironlake_dual_lvds;
|
|
|
|
} else {
|
2010-12-15 04:04:54 +08:00
|
|
|
if (refclk == 100000)
|
2010-02-05 09:14:17 +08:00
|
|
|
limit = &intel_limits_ironlake_single_lvds_100m;
|
|
|
|
else
|
|
|
|
limit = &intel_limits_ironlake_single_lvds;
|
|
|
|
}
|
2013-04-19 17:14:33 +08:00
|
|
|
} else
|
2010-02-05 09:14:17 +08:00
|
|
|
limit = &intel_limits_ironlake_dac;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
|
|
|
return limit;
|
|
|
|
}
|
|
|
|
|
2009-03-18 20:13:23 +08:00
|
|
|
static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
2012-11-27 00:22:09 +08:00
|
|
|
if (intel_is_dual_link_lvds(dev))
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_g4x_dual_channel_lvds;
|
2009-03-18 20:13:23 +08:00
|
|
|
else
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_g4x_single_channel_lvds;
|
2009-03-18 20:13:23 +08:00
|
|
|
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
|
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_g4x_hdmi;
|
2009-03-18 20:13:23 +08:00
|
|
|
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_g4x_sdvo;
|
2009-03-18 20:13:23 +08:00
|
|
|
} else /* The option is for other outputs */
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_i9xx_sdvo;
|
2009-03-18 20:13:23 +08:00
|
|
|
|
|
|
|
return limit;
|
|
|
|
}
|
|
|
|
|
2010-12-15 04:04:54 +08:00
|
|
|
static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
2009-10-23 07:11:14 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev))
|
2010-12-15 04:04:54 +08:00
|
|
|
limit = intel_ironlake_limit(crtc, refclk);
|
2009-06-05 15:38:42 +08:00
|
|
|
else if (IS_G4X(dev)) {
|
2009-03-18 20:13:23 +08:00
|
|
|
limit = intel_g4x_limit(crtc);
|
2009-12-04 06:14:42 +08:00
|
|
|
} else if (IS_PINEVIEW(dev)) {
|
2009-02-23 15:19:16 +08:00
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
2009-12-04 06:14:42 +08:00
|
|
|
limit = &intel_limits_pineview_lvds;
|
2009-02-23 15:19:16 +08:00
|
|
|
else
|
2009-12-04 06:14:42 +08:00
|
|
|
limit = &intel_limits_pineview_sdvo;
|
2012-06-16 02:55:13 +08:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG))
|
|
|
|
limit = &intel_limits_vlv_dac;
|
|
|
|
else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
|
|
|
|
limit = &intel_limits_vlv_hdmi;
|
|
|
|
else
|
|
|
|
limit = &intel_limits_vlv_dp;
|
2010-09-17 07:32:17 +08:00
|
|
|
} else if (!IS_GEN2(dev)) {
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
|
|
|
limit = &intel_limits_i9xx_lvds;
|
|
|
|
else
|
|
|
|
limit = &intel_limits_i9xx_sdvo;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} else {
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_i8xx_lvds;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
else
|
2009-06-06 10:22:17 +08:00
|
|
|
limit = &intel_limits_i8xx_dvo;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
return limit;
|
|
|
|
}
|
|
|
|
|
2009-12-04 06:14:42 +08:00
|
|
|
/* m1 is reserved as 0 in Pineview, n is a ring counter */
|
|
|
|
static void pineview_clock(int refclk, intel_clock_t *clock)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2009-02-23 15:19:16 +08:00
|
|
|
clock->m = clock->m2 + 2;
|
|
|
|
clock->p = clock->p1 * clock->p2;
|
|
|
|
clock->vco = refclk * clock->m / clock->n;
|
|
|
|
clock->dot = clock->vco / clock->p;
|
|
|
|
}
|
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
|
|
|
|
{
|
|
|
|
return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
|
|
|
|
}
|
|
|
|
|
2009-02-23 15:19:16 +08:00
|
|
|
static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
|
|
|
|
{
|
2009-12-04 06:14:42 +08:00
|
|
|
if (IS_PINEVIEW(dev)) {
|
|
|
|
pineview_clock(refclk, clock);
|
2009-02-23 15:19:16 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-04-20 23:19:46 +08:00
|
|
|
clock->m = i9xx_dpll_compute_m(clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
clock->p = clock->p1 * clock->p2;
|
|
|
|
clock->vco = refclk * clock->m / (clock->n + 2);
|
|
|
|
clock->dot = clock->vco / clock->p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether any output on the specified pipe is of the specified type
|
|
|
|
*/
|
2010-09-09 22:14:28 +08:00
|
|
|
bool intel_pipe_has_type(struct drm_crtc *crtc, int type)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2010-09-09 22:14:28 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
2012-07-05 15:50:24 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->type == type)
|
2010-09-09 22:14:28 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2009-02-24 07:36:40 +08:00
|
|
|
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/**
|
|
|
|
* Returns whether the given set of divisors are valid for a given refclk with
|
|
|
|
* the given connectors.
|
|
|
|
*/
|
|
|
|
|
2010-12-15 04:04:54 +08:00
|
|
|
static bool intel_PLL_is_valid(struct drm_device *dev,
|
|
|
|
const intel_limit_t *limit,
|
|
|
|
const intel_clock_t *clock)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("p1 out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->p < limit->p.min || limit->p.max < clock->p)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("p out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("m2 out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("m1 out of range\n");
|
2009-12-04 06:14:42 +08:00
|
|
|
if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev))
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("m1 <= m2\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->m < limit->m.min || limit->m.max < clock->m)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("m out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->n < limit->n.min || limit->n.max < clock->n)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("n out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("vco out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
|
|
|
|
* connector, etc., rather than just a single range.
|
|
|
|
*/
|
|
|
|
if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
|
2011-08-17 03:34:10 +08:00
|
|
|
INTELPllInvalid("dot out of range\n");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
static bool
|
|
|
|
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
2012-01-11 07:09:36 +08:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock)
|
2009-03-18 20:13:27 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
intel_clock_t clock;
|
|
|
|
int err = target;
|
|
|
|
|
2012-11-27 00:22:08 +08:00
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/*
|
2012-11-27 00:22:08 +08:00
|
|
|
* For LVDS just rely on its current settings for dual-channel.
|
|
|
|
* We haven't figured out how to reliably set up different
|
|
|
|
* single/dual channel state, if we even can.
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
*/
|
2012-11-27 00:22:09 +08:00
|
|
|
if (intel_is_dual_link_lvds(dev))
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
|
else
|
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
|
|
} else {
|
|
|
|
if (target < limit->p2.dot_limit)
|
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
|
|
else
|
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
|
}
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
memset(best_clock, 0, sizeof(*best_clock));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-11-20 11:24:18 +08:00
|
|
|
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
|
|
|
|
clock.m1++) {
|
|
|
|
for (clock.m2 = limit->m2.min;
|
|
|
|
clock.m2 <= limit->m2.max; clock.m2++) {
|
2009-12-04 06:14:42 +08:00
|
|
|
/* m1 is always 0 in Pineview */
|
|
|
|
if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev))
|
2009-11-20 11:24:18 +08:00
|
|
|
break;
|
|
|
|
for (clock.n = limit->n.min;
|
|
|
|
clock.n <= limit->n.max; clock.n++) {
|
|
|
|
for (clock.p1 = limit->p1.min;
|
|
|
|
clock.p1 <= limit->p1.max; clock.p1++) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int this_err;
|
|
|
|
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, refclk, &clock);
|
2010-12-15 04:04:54 +08:00
|
|
|
if (!intel_PLL_is_valid(dev, limit,
|
|
|
|
&clock))
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
continue;
|
2012-01-11 07:09:36 +08:00
|
|
|
if (match_clock &&
|
|
|
|
clock.p != match_clock->p)
|
|
|
|
continue;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
this_err = abs(clock.dot - target);
|
|
|
|
if (this_err < err) {
|
|
|
|
*best_clock = clock;
|
|
|
|
err = this_err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (err != target);
|
|
|
|
}
|
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
static bool
|
|
|
|
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
2012-01-11 07:09:36 +08:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock)
|
2009-03-18 20:13:27 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
intel_clock_t clock;
|
|
|
|
int max_n;
|
|
|
|
bool found;
|
2010-07-03 04:43:30 +08:00
|
|
|
/* approximately equals target * 0.00585 */
|
|
|
|
int err_most = (target >> 8) + (target >> 9);
|
2009-03-18 20:13:27 +08:00
|
|
|
found = false;
|
|
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
2012-11-27 00:22:09 +08:00
|
|
|
if (intel_is_dual_link_lvds(dev))
|
2009-03-18 20:13:27 +08:00
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
|
else
|
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
|
|
} else {
|
|
|
|
if (target < limit->p2.dot_limit)
|
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
|
|
else
|
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(best_clock, 0, sizeof(*best_clock));
|
|
|
|
max_n = limit->n.max;
|
2010-03-29 21:41:47 +08:00
|
|
|
/* based on hardware requirement, prefer smaller n to precision */
|
2009-03-18 20:13:27 +08:00
|
|
|
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
2010-03-29 21:41:47 +08:00
|
|
|
/* based on hardware requirement, prefere larger m1,m2 */
|
2009-03-18 20:13:27 +08:00
|
|
|
for (clock.m1 = limit->m1.max;
|
|
|
|
clock.m1 >= limit->m1.min; clock.m1--) {
|
|
|
|
for (clock.m2 = limit->m2.max;
|
|
|
|
clock.m2 >= limit->m2.min; clock.m2--) {
|
|
|
|
for (clock.p1 = limit->p1.max;
|
|
|
|
clock.p1 >= limit->p1.min; clock.p1--) {
|
|
|
|
int this_err;
|
|
|
|
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, refclk, &clock);
|
2010-12-15 04:04:54 +08:00
|
|
|
if (!intel_PLL_is_valid(dev, limit,
|
|
|
|
&clock))
|
2009-03-18 20:13:27 +08:00
|
|
|
continue;
|
2010-12-15 04:04:54 +08:00
|
|
|
|
|
|
|
this_err = abs(clock.dot - target);
|
2009-03-18 20:13:27 +08:00
|
|
|
if (this_err < err_most) {
|
|
|
|
*best_clock = clock;
|
|
|
|
err_most = this_err;
|
|
|
|
max_n = clock.n;
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2012-06-16 02:55:13 +08:00
|
|
|
static bool
|
|
|
|
intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
intel_clock_t *best_clock)
|
|
|
|
{
|
|
|
|
u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
|
|
|
|
u32 m, n, fastclk;
|
|
|
|
u32 updrate, minupdate, fracbits, p;
|
|
|
|
unsigned long bestppm, ppm, absppm;
|
|
|
|
int dotclk, flag;
|
|
|
|
|
2012-07-25 20:49:18 +08:00
|
|
|
flag = 0;
|
2012-06-16 02:55:13 +08:00
|
|
|
dotclk = target * 1000;
|
|
|
|
bestppm = 1000000;
|
|
|
|
ppm = absppm = 0;
|
|
|
|
fastclk = dotclk / (2*100);
|
|
|
|
updrate = 0;
|
|
|
|
minupdate = 19200;
|
|
|
|
fracbits = 1;
|
|
|
|
n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0;
|
|
|
|
bestm1 = bestm2 = bestp1 = bestp2 = 0;
|
|
|
|
|
|
|
|
/* based on hardware requirement, prefer smaller n to precision */
|
|
|
|
for (n = limit->n.min; n <= ((refclk) / minupdate); n++) {
|
|
|
|
updrate = refclk / n;
|
|
|
|
for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) {
|
|
|
|
for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) {
|
|
|
|
if (p2 > 10)
|
|
|
|
p2 = p2 - 1;
|
|
|
|
p = p1 * p2;
|
|
|
|
/* based on hardware requirement, prefer bigger m1,m2 values */
|
|
|
|
for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) {
|
|
|
|
m2 = (((2*(fastclk * p * n / m1 )) +
|
|
|
|
refclk) / (2*refclk));
|
|
|
|
m = m1 * m2;
|
|
|
|
vco = updrate * m;
|
|
|
|
if (vco >= limit->vco.min && vco < limit->vco.max) {
|
|
|
|
ppm = 1000000 * ((vco / p) - fastclk) / fastclk;
|
|
|
|
absppm = (ppm > 0) ? ppm : (-ppm);
|
|
|
|
if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) {
|
|
|
|
bestppm = 0;
|
|
|
|
flag = 1;
|
|
|
|
}
|
|
|
|
if (absppm < bestppm - 10) {
|
|
|
|
bestppm = absppm;
|
|
|
|
flag = 1;
|
|
|
|
}
|
|
|
|
if (flag) {
|
|
|
|
bestn = n;
|
|
|
|
bestm1 = m1;
|
|
|
|
bestm2 = m2;
|
|
|
|
bestp1 = p1;
|
|
|
|
bestp2 = p2;
|
|
|
|
flag = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
best_clock->n = bestn;
|
|
|
|
best_clock->m1 = bestm1;
|
|
|
|
best_clock->m2 = bestm2;
|
|
|
|
best_clock->p1 = bestp1;
|
|
|
|
best_clock->p2 = bestp2;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2009-04-08 07:16:42 +08:00
|
|
|
|
drm/i915: add TRANSCODER_EDP
Before Haswell we used to have the CPU pipes and the PCH transcoders.
We had the same amount of pipes and transcoders, and there was a 1:1
mapping between them. After Haswell what we used to call CPU pipe was
split into CPU pipe and CPU transcoder. So now we have 3 CPU pipes (A,
B and C), 4 CPU transcoders (A, B, C and EDP) and 1 PCH transcoder
(only used for VGA).
For all the outputs except for EDP we have an 1:1 mapping on the CPU
pipes and CPU transcoders, so if you're using CPU pipe A you have to
use CPU transcoder A. When have an eDP output you have to use
transcoder EDP and you can attach this CPU transcoder to any of the 3
CPU pipes. When using VGA you need to select a pair of matching CPU
pipes/transcoders (A/A, B/B, C/C) and you also need to enable/use the
PCH transcoder.
For now we're just creating the cpu_transcoder definitions and setting
cpu_transcoder to TRANSCODER_EDP on DDI eDP code, but none of the
registers was ported to use transcoder instead of pipe. The goal is to
keep the code backwards-compatible since on all cases except when
using eDP we must have pipe == cpu_transcoder.
V2: Comment the haswell_crtc_off chunk, suggested by Damien Lespiau
and Daniel Vetter.
We currently need the haswell_crtc_off chunk because TRANSCODER_EDP
can be used by any CRTC, so when you stop using it you have to stop
saying you're using it, otherwise you may have at some point 2 CRTCs
claiming they're using TRANSCODER_EDP (a disabled CRTC and an enabled
one), then the HW state readout code will get completely confused.
In other words:
Imagine the following case:
xrandr --output eDP1 --auto --crtc 0
xrandr --output eDP1 --off
xrandr --output eDP1 --auto --crtc 2
After the last command you could get a "pipe A assertion failure
(expected off, current on)" because CRTC 0 still claims it's using
TRANSCODER_EDP, so the HW state readout function will read it
(through PIPECONF) and expect it to be off, when it's actually on
because it's being used by CRTC 2.
So when we make "intel_crtc->cpu_transcoder = intel_crtc->pipe" we
make sure we're pointing to our own original CRTC which is certainly
not used by any other CRTC.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-10-25 01:59:34 +08:00
|
|
|
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
2013-04-18 02:15:07 +08:00
|
|
|
return intel_crtc->config.cpu_transcoder;
|
drm/i915: add TRANSCODER_EDP
Before Haswell we used to have the CPU pipes and the PCH transcoders.
We had the same amount of pipes and transcoders, and there was a 1:1
mapping between them. After Haswell what we used to call CPU pipe was
split into CPU pipe and CPU transcoder. So now we have 3 CPU pipes (A,
B and C), 4 CPU transcoders (A, B, C and EDP) and 1 PCH transcoder
(only used for VGA).
For all the outputs except for EDP we have an 1:1 mapping on the CPU
pipes and CPU transcoders, so if you're using CPU pipe A you have to
use CPU transcoder A. When have an eDP output you have to use
transcoder EDP and you can attach this CPU transcoder to any of the 3
CPU pipes. When using VGA you need to select a pair of matching CPU
pipes/transcoders (A/A, B/B, C/C) and you also need to enable/use the
PCH transcoder.
For now we're just creating the cpu_transcoder definitions and setting
cpu_transcoder to TRANSCODER_EDP on DDI eDP code, but none of the
registers was ported to use transcoder instead of pipe. The goal is to
keep the code backwards-compatible since on all cases except when
using eDP we must have pipe == cpu_transcoder.
V2: Comment the haswell_crtc_off chunk, suggested by Damien Lespiau
and Daniel Vetter.
We currently need the haswell_crtc_off chunk because TRANSCODER_EDP
can be used by any CRTC, so when you stop using it you have to stop
saying you're using it, otherwise you may have at some point 2 CRTCs
claiming they're using TRANSCODER_EDP (a disabled CRTC and an enabled
one), then the HW state readout code will get completely confused.
In other words:
Imagine the following case:
xrandr --output eDP1 --auto --crtc 0
xrandr --output eDP1 --off
xrandr --output eDP1 --auto --crtc 2
After the last command you could get a "pipe A assertion failure
(expected off, current on)" because CRTC 0 still claims it's using
TRANSCODER_EDP, so the HW state readout function will read it
(through PIPECONF) and expect it to be off, when it's actually on
because it's being used by CRTC 2.
So when we make "intel_crtc->cpu_transcoder = intel_crtc->pipe" we
make sure we're pointing to our own original CRTC which is certainly
not used by any other CRTC.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-10-25 01:59:34 +08:00
|
|
|
}
|
|
|
|
|
2012-05-05 04:18:15 +08:00
|
|
|
static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
u32 frame, frame_reg = PIPEFRAME(pipe);
|
|
|
|
|
|
|
|
frame = I915_READ(frame_reg);
|
|
|
|
|
|
|
|
if (wait_for(I915_READ_NOTRACE(frame_reg) != frame, 50))
|
|
|
|
DRM_DEBUG_KMS("vblank wait timed out\n");
|
|
|
|
}
|
|
|
|
|
2010-08-19 04:20:54 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
void intel_wait_for_vblank(struct drm_device *dev, int pipe)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2010-08-19 04:20:54 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2011-02-08 04:26:52 +08:00
|
|
|
int pipestat_reg = PIPESTAT(pipe);
|
2010-08-19 04:20:54 +08:00
|
|
|
|
2012-05-05 04:18:15 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 5) {
|
|
|
|
ironlake_wait_for_vblank(dev, pipe);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-06 03:25:43 +08:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
I915_WRITE(pipestat_reg,
|
|
|
|
I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS);
|
|
|
|
|
2010-08-19 04:20:54 +08:00
|
|
|
/* Wait for vblank interrupt bit to set */
|
2010-08-24 00:43:35 +08:00
|
|
|
if (wait_for(I915_READ(pipestat_reg) &
|
|
|
|
PIPE_VBLANK_INTERRUPT_STATUS,
|
|
|
|
50))
|
2010-08-19 04:20:54 +08:00
|
|
|
DRM_DEBUG_KMS("vblank wait timed out\n");
|
|
|
|
}
|
|
|
|
|
2010-10-03 15:33:06 +08:00
|
|
|
/*
|
|
|
|
* intel_wait_for_pipe_off - wait for pipe to turn off
|
2010-08-19 04:20:54 +08:00
|
|
|
* @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.
|
|
|
|
*
|
2010-10-03 15:33:06 +08:00
|
|
|
* 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).
|
2010-10-03 17:56:11 +08:00
|
|
|
*
|
2010-08-19 04:20:54 +08:00
|
|
|
*/
|
2010-10-03 17:56:11 +08:00
|
|
|
void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
|
2010-08-19 04:20:54 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-10-24 04:29:59 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
pipe);
|
2010-10-03 15:33:06 +08:00
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2012-10-24 04:29:59 +08:00
|
|
|
int reg = PIPECONF(cpu_transcoder);
|
2010-10-03 15:33:06 +08:00
|
|
|
|
|
|
|
/* Wait for the Pipe State to go off */
|
2010-10-03 17:56:11 +08:00
|
|
|
if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
|
|
|
|
100))
|
2012-07-09 15:51:57 +08:00
|
|
|
WARN(1, "pipe_off wait timed out\n");
|
2010-10-03 15:33:06 +08:00
|
|
|
} else {
|
2012-05-05 04:18:14 +08:00
|
|
|
u32 last_line, line_mask;
|
2010-10-03 17:56:11 +08:00
|
|
|
int reg = PIPEDSL(pipe);
|
2010-10-03 15:33:06 +08:00
|
|
|
unsigned long timeout = jiffies + msecs_to_jiffies(100);
|
|
|
|
|
2012-05-05 04:18:14 +08:00
|
|
|
if (IS_GEN2(dev))
|
|
|
|
line_mask = DSL_LINEMASK_GEN2;
|
|
|
|
else
|
|
|
|
line_mask = DSL_LINEMASK_GEN3;
|
|
|
|
|
2010-10-03 15:33:06 +08:00
|
|
|
/* Wait for the display line to settle */
|
|
|
|
do {
|
2012-05-05 04:18:14 +08:00
|
|
|
last_line = I915_READ(reg) & line_mask;
|
2010-10-03 15:33:06 +08:00
|
|
|
mdelay(5);
|
2012-05-05 04:18:14 +08:00
|
|
|
} while (((I915_READ(reg) & line_mask) != last_line) &&
|
2010-10-03 15:33:06 +08:00
|
|
|
time_after(timeout, jiffies));
|
|
|
|
if (time_after(jiffies, timeout))
|
2012-07-09 15:51:57 +08:00
|
|
|
WARN(1, "pipe_off wait timed out\n");
|
2010-10-03 15:33:06 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-12-14 00:09:00 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
|
|
|
|
struct intel_digital_port *port)
|
|
|
|
{
|
|
|
|
u32 bit;
|
|
|
|
|
2012-12-14 00:09:03 +08:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
|
switch(port->port) {
|
|
|
|
case PORT_B:
|
|
|
|
bit = SDE_PORTB_HOTPLUG;
|
|
|
|
break;
|
|
|
|
case PORT_C:
|
|
|
|
bit = SDE_PORTC_HOTPLUG;
|
|
|
|
break;
|
|
|
|
case PORT_D:
|
|
|
|
bit = SDE_PORTD_HOTPLUG;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch(port->port) {
|
|
|
|
case PORT_B:
|
|
|
|
bit = SDE_PORTB_HOTPLUG_CPT;
|
|
|
|
break;
|
|
|
|
case PORT_C:
|
|
|
|
bit = SDE_PORTC_HOTPLUG_CPT;
|
|
|
|
break;
|
|
|
|
case PORT_D:
|
|
|
|
bit = SDE_PORTD_HOTPLUG_CPT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
2012-12-14 00:09:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return I915_READ(SDEISR) & bit;
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
static const char *state_string(bool enabled)
|
|
|
|
{
|
|
|
|
return enabled ? "on" : "off";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only for pre-ILK configs */
|
|
|
|
static void assert_pll(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, bool state)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
bool cur_state;
|
|
|
|
|
|
|
|
reg = DPLL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
cur_state = !!(val & DPLL_VCO_ENABLE);
|
|
|
|
WARN(cur_state != state,
|
|
|
|
"PLL state assertion failure (expected %s, current %s)\n",
|
|
|
|
state_string(state), state_string(cur_state));
|
|
|
|
}
|
|
|
|
#define assert_pll_enabled(d, p) assert_pll(d, p, true)
|
|
|
|
#define assert_pll_disabled(d, p) assert_pll(d, p, false)
|
|
|
|
|
2011-01-04 04:14:26 +08:00
|
|
|
/* For ILK+ */
|
|
|
|
static void assert_pch_pll(struct drm_i915_private *dev_priv,
|
2012-05-21 01:10:50 +08:00
|
|
|
struct intel_pch_pll *pll,
|
|
|
|
struct intel_crtc *crtc,
|
|
|
|
bool state)
|
2011-01-04 04:14:26 +08:00
|
|
|
{
|
|
|
|
u32 val;
|
|
|
|
bool cur_state;
|
|
|
|
|
2012-05-10 02:37:17 +08:00
|
|
|
if (HAS_PCH_LPT(dev_priv->dev)) {
|
|
|
|
DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-21 01:10:50 +08:00
|
|
|
if (WARN (!pll,
|
|
|
|
"asserting PCH PLL %s with no PLL\n", state_string(state)))
|
2012-04-21 00:11:53 +08:00
|
|
|
return;
|
|
|
|
|
2012-05-21 01:10:50 +08:00
|
|
|
val = I915_READ(pll->pll_reg);
|
|
|
|
cur_state = !!(val & DPLL_VCO_ENABLE);
|
|
|
|
WARN(cur_state != state,
|
|
|
|
"PCH PLL state for reg %x assertion failure (expected %s, current %s), val=%08x\n",
|
|
|
|
pll->pll_reg, state_string(state), state_string(cur_state), val);
|
|
|
|
|
|
|
|
/* Make sure the selected PLL is correctly attached to the transcoder */
|
|
|
|
if (crtc && HAS_PCH_CPT(dev_priv->dev)) {
|
2011-10-13 00:27:42 +08:00
|
|
|
u32 pch_dpll;
|
|
|
|
|
|
|
|
pch_dpll = I915_READ(PCH_DPLL_SEL);
|
2012-05-21 01:10:50 +08:00
|
|
|
cur_state = pll->pll_reg == _PCH_DPLL_B;
|
|
|
|
if (!WARN(((pch_dpll >> (4 * crtc->pipe)) & 1) != cur_state,
|
2013-04-17 22:48:50 +08:00
|
|
|
"PLL[%d] not attached to this transcoder %c: %08x\n",
|
|
|
|
cur_state, pipe_name(crtc->pipe), pch_dpll)) {
|
2012-05-21 01:10:50 +08:00
|
|
|
cur_state = !!(val >> (4*crtc->pipe + 3));
|
|
|
|
WARN(cur_state != state,
|
2013-04-17 22:48:50 +08:00
|
|
|
"PLL[%d] not %s on this transcoder %c: %08x\n",
|
2012-05-21 01:10:50 +08:00
|
|
|
pll->pll_reg == _PCH_DPLL_B,
|
|
|
|
state_string(state),
|
2013-04-17 22:48:50 +08:00
|
|
|
pipe_name(crtc->pipe),
|
2012-05-21 01:10:50 +08:00
|
|
|
val);
|
|
|
|
}
|
2011-10-13 00:27:42 +08:00
|
|
|
}
|
2011-01-04 04:14:26 +08:00
|
|
|
}
|
2012-05-21 01:10:50 +08:00
|
|
|
#define assert_pch_pll_enabled(d, p, c) assert_pch_pll(d, p, c, true)
|
|
|
|
#define assert_pch_pll_disabled(d, p, c) assert_pch_pll(d, p, c, false)
|
2011-01-04 04:14:26 +08:00
|
|
|
|
|
|
|
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, bool state)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
bool cur_state;
|
2012-10-25 02:06:19 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
pipe);
|
2011-01-04 04:14:26 +08:00
|
|
|
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev_priv->dev)) {
|
|
|
|
/* DDI does not have a specific FDI_TX register */
|
2012-10-25 02:06:19 +08:00
|
|
|
reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
|
2012-05-10 02:37:18 +08:00
|
|
|
val = I915_READ(reg);
|
2012-10-25 02:06:19 +08:00
|
|
|
cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
|
2012-05-10 02:37:18 +08:00
|
|
|
} else {
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
cur_state = !!(val & FDI_TX_ENABLE);
|
|
|
|
}
|
2011-01-04 04:14:26 +08:00
|
|
|
WARN(cur_state != state,
|
|
|
|
"FDI TX state assertion failure (expected %s, current %s)\n",
|
|
|
|
state_string(state), state_string(cur_state));
|
|
|
|
}
|
|
|
|
#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
|
|
|
|
#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
|
|
|
|
|
|
|
|
static void assert_fdi_rx(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, bool state)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
bool cur_state;
|
|
|
|
|
2012-11-20 23:27:35 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
cur_state = !!(val & FDI_RX_ENABLE);
|
2011-01-04 04:14:26 +08:00
|
|
|
WARN(cur_state != state,
|
|
|
|
"FDI RX state assertion failure (expected %s, current %s)\n",
|
|
|
|
state_string(state), state_string(cur_state));
|
|
|
|
}
|
|
|
|
#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
|
|
|
|
#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
|
|
|
|
|
|
|
|
static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
/* ILK FDI PLL is always enabled */
|
|
|
|
if (dev_priv->info->gen == 5)
|
|
|
|
return;
|
|
|
|
|
2012-05-10 02:37:18 +08:00
|
|
|
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev_priv->dev))
|
2012-05-10 02:37:18 +08:00
|
|
|
return;
|
|
|
|
|
2011-01-04 04:14:26 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n");
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:32 +08:00
|
|
|
static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int pp_reg, lvds_reg;
|
|
|
|
u32 val;
|
|
|
|
enum pipe panel_pipe = PIPE_A;
|
2011-08-25 21:37:45 +08:00
|
|
|
bool locked = true;
|
2011-01-05 07:09:32 +08:00
|
|
|
|
|
|
|
if (HAS_PCH_SPLIT(dev_priv->dev)) {
|
|
|
|
pp_reg = PCH_PP_CONTROL;
|
|
|
|
lvds_reg = PCH_LVDS;
|
|
|
|
} else {
|
|
|
|
pp_reg = PP_CONTROL;
|
|
|
|
lvds_reg = LVDS;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = I915_READ(pp_reg);
|
|
|
|
if (!(val & PANEL_POWER_ON) ||
|
|
|
|
((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS))
|
|
|
|
locked = false;
|
|
|
|
|
|
|
|
if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT)
|
|
|
|
panel_pipe = PIPE_B;
|
|
|
|
|
|
|
|
WARN(panel_pipe == pipe && locked,
|
|
|
|
"panel assertion failure, pipe %c regs locked\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
pipe_name(pipe));
|
2011-01-05 07:09:32 +08:00
|
|
|
}
|
|
|
|
|
2011-12-14 05:19:38 +08:00
|
|
|
void assert_pipe(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, bool state)
|
2011-01-05 07:09:30 +08:00
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
2011-01-05 07:09:33 +08:00
|
|
|
bool cur_state;
|
2012-10-24 04:29:59 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
pipe);
|
2011-01-05 07:09:30 +08:00
|
|
|
|
2012-01-22 08:36:48 +08:00
|
|
|
/* if we need the pipe A quirk it must be always on */
|
|
|
|
if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
|
|
|
|
state = true;
|
|
|
|
|
2013-05-03 23:15:36 +08:00
|
|
|
if (!intel_display_power_enabled(dev_priv->dev,
|
|
|
|
POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
|
2013-01-30 02:35:19 +08:00
|
|
|
cur_state = false;
|
|
|
|
} else {
|
|
|
|
reg = PIPECONF(cpu_transcoder);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
cur_state = !!(val & PIPECONF_ENABLE);
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:33 +08:00
|
|
|
WARN(cur_state != state,
|
|
|
|
"pipe %c assertion failure (expected %s, current %s)\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
pipe_name(pipe), state_string(state), state_string(cur_state));
|
2011-01-05 07:09:30 +08:00
|
|
|
}
|
|
|
|
|
2012-01-17 07:01:13 +08:00
|
|
|
static void assert_plane(struct drm_i915_private *dev_priv,
|
|
|
|
enum plane plane, bool state)
|
2011-01-05 07:09:30 +08:00
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
2012-01-17 07:01:13 +08:00
|
|
|
bool cur_state;
|
2011-01-05 07:09:30 +08:00
|
|
|
|
|
|
|
reg = DSPCNTR(plane);
|
|
|
|
val = I915_READ(reg);
|
2012-01-17 07:01:13 +08:00
|
|
|
cur_state = !!(val & DISPLAY_PLANE_ENABLE);
|
|
|
|
WARN(cur_state != state,
|
|
|
|
"plane %c assertion failure (expected %s, current %s)\n",
|
|
|
|
plane_name(plane), state_string(state), state_string(cur_state));
|
2011-01-05 07:09:30 +08:00
|
|
|
}
|
|
|
|
|
2012-01-17 07:01:13 +08:00
|
|
|
#define assert_plane_enabled(d, p) assert_plane(d, p, true)
|
|
|
|
#define assert_plane_disabled(d, p) assert_plane(d, p, false)
|
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
static void assert_planes_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg, i;
|
|
|
|
u32 val;
|
|
|
|
int cur_pipe;
|
|
|
|
|
2011-02-03 04:28:02 +08:00
|
|
|
/* Planes are fixed to pipes on ILK+ */
|
2013-03-09 02:46:00 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev_priv->dev) || IS_VALLEYVIEW(dev_priv->dev)) {
|
2011-10-08 02:38:42 +08:00
|
|
|
reg = DSPCNTR(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
WARN((val & DISPLAY_PLANE_ENABLE),
|
|
|
|
"plane %c assertion failure, should be disabled but not\n",
|
|
|
|
plane_name(pipe));
|
2011-02-03 04:28:02 +08:00
|
|
|
return;
|
2011-10-08 02:38:42 +08:00
|
|
|
}
|
2011-02-03 04:28:02 +08:00
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
/* Need to check both planes against the pipe */
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
reg = DSPCNTR(i);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
|
|
|
|
DISPPLANE_SEL_PIPE_SHIFT;
|
|
|
|
WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
|
2011-02-08 04:26:52 +08:00
|
|
|
"plane %c assertion failure, should be off on pipe %c but is still active\n",
|
|
|
|
plane_name(i), pipe_name(pipe));
|
2011-01-05 07:09:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-29 00:55:38 +08:00
|
|
|
static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg, i;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
if (!IS_VALLEYVIEW(dev_priv->dev))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Need to check both planes against the pipe */
|
|
|
|
for (i = 0; i < dev_priv->num_plane; i++) {
|
|
|
|
reg = SPCNTR(pipe, i);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
WARN((val & SP_ENABLE),
|
2013-04-17 22:48:51 +08:00
|
|
|
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
|
|
|
|
sprite_name(pipe, i), pipe_name(pipe));
|
2013-03-29 00:55:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:34 +08:00
|
|
|
static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
|
|
|
|
{
|
|
|
|
u32 val;
|
|
|
|
bool enabled;
|
|
|
|
|
2012-05-10 02:37:17 +08:00
|
|
|
if (HAS_PCH_LPT(dev_priv->dev)) {
|
|
|
|
DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:34 +08:00
|
|
|
val = I915_READ(PCH_DREF_CONTROL);
|
|
|
|
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
|
|
|
|
DREF_SUPERSPREAD_SOURCE_MASK));
|
|
|
|
WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
2011-01-05 07:09:34 +08:00
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
bool enabled;
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
reg = PCH_TRANSCONF(pipe);
|
2011-01-05 07:09:34 +08:00
|
|
|
val = I915_READ(reg);
|
|
|
|
enabled = !!(val & TRANS_ENABLE);
|
2011-02-08 04:26:52 +08:00
|
|
|
WARN(enabled,
|
|
|
|
"transcoder assertion failed, should be off on pipe %c but is still active\n",
|
|
|
|
pipe_name(pipe));
|
2011-01-05 07:09:34 +08:00
|
|
|
}
|
|
|
|
|
2011-08-07 01:39:45 +08:00
|
|
|
static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, u32 port_sel, u32 val)
|
2011-07-26 13:12:43 +08:00
|
|
|
{
|
|
|
|
if ((val & DP_PORT_EN) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
|
|
|
u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
|
|
|
|
u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
|
|
|
|
if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if ((val & DP_PIPE_MASK) != (pipe << 30))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-08-07 01:35:34 +08:00
|
|
|
static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, u32 val)
|
|
|
|
{
|
2013-02-20 03:21:46 +08:00
|
|
|
if ((val & SDVO_ENABLE) == 0)
|
2011-08-07 01:35:34 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
2013-02-20 03:21:46 +08:00
|
|
|
if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe))
|
2011-08-07 01:35:34 +08:00
|
|
|
return false;
|
|
|
|
} else {
|
2013-02-20 03:21:46 +08:00
|
|
|
if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe))
|
2011-08-07 01:35:34 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool lvds_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, u32 val)
|
|
|
|
{
|
|
|
|
if ((val & LVDS_PORT_EN) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
|
|
|
if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if ((val & LVDS_PIPE_MASK) != LVDS_PIPE(pipe))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, u32 val)
|
|
|
|
{
|
|
|
|
if ((val & ADPA_DAC_ENABLE) == 0)
|
|
|
|
return false;
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
|
|
|
if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if ((val & ADPA_PIPE_SELECT_MASK) != ADPA_PIPE_SELECT(pipe))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-03 04:28:03 +08:00
|
|
|
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
|
2011-07-26 13:12:43 +08:00
|
|
|
enum pipe pipe, int reg, u32 port_sel)
|
2011-02-03 04:28:03 +08:00
|
|
|
{
|
2011-02-08 05:46:40 +08:00
|
|
|
u32 val = I915_READ(reg);
|
2011-08-07 01:39:45 +08:00
|
|
|
WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
|
2011-02-03 04:28:03 +08:00
|
|
|
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
reg, pipe_name(pipe));
|
2012-06-05 17:03:40 +08:00
|
|
|
|
2012-09-11 03:58:29 +08:00
|
|
|
WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
|
|
|
|
&& (val & DP_PIPEB_SELECT),
|
2012-06-05 17:03:40 +08:00
|
|
|
"IBX PCH dp port still using transcoder B\n");
|
2011-02-03 04:28:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe, int reg)
|
|
|
|
{
|
2011-02-08 05:46:40 +08:00
|
|
|
u32 val = I915_READ(reg);
|
2012-08-13 11:08:33 +08:00
|
|
|
WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
|
2011-10-08 02:38:43 +08:00
|
|
|
"PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
reg, pipe_name(pipe));
|
2012-06-05 17:03:40 +08:00
|
|
|
|
2013-02-20 03:21:46 +08:00
|
|
|
WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
|
2012-09-11 03:58:29 +08:00
|
|
|
&& (val & SDVO_PIPE_B_SELECT),
|
2012-06-05 17:03:40 +08:00
|
|
|
"IBX PCH hdmi port still using transcoder B\n");
|
2011-02-03 04:28:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
2011-07-26 13:12:43 +08:00
|
|
|
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
|
|
|
|
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
|
|
|
|
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
|
2011-02-03 04:28:03 +08:00
|
|
|
|
|
|
|
reg = PCH_ADPA;
|
|
|
|
val = I915_READ(reg);
|
2012-08-13 11:08:33 +08:00
|
|
|
WARN(adpa_pipe_enabled(dev_priv, pipe, val),
|
2011-02-03 04:28:03 +08:00
|
|
|
"PCH VGA enabled on transcoder %c, should be disabled\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
pipe_name(pipe));
|
2011-02-03 04:28:03 +08:00
|
|
|
|
|
|
|
reg = PCH_LVDS;
|
|
|
|
val = I915_READ(reg);
|
2012-08-13 11:08:33 +08:00
|
|
|
WARN(lvds_pipe_enabled(dev_priv, pipe, val),
|
2011-02-03 04:28:03 +08:00
|
|
|
"PCH LVDS enabled on transcoder %c, should be disabled\n",
|
2011-02-08 04:26:52 +08:00
|
|
|
pipe_name(pipe));
|
2011-02-03 04:28:03 +08:00
|
|
|
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIB);
|
|
|
|
assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIC);
|
|
|
|
assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
|
2011-02-03 04:28:03 +08:00
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:33 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
2012-07-19 01:22:30 +08:00
|
|
|
*
|
|
|
|
* Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
|
2011-01-05 07:09:33 +08:00
|
|
|
*/
|
|
|
|
static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
2013-04-11 22:29:09 +08:00
|
|
|
assert_pipe_disabled(dev_priv, pipe);
|
|
|
|
|
2011-01-05 07:09:33 +08:00
|
|
|
/* No really, not for ILK+ */
|
2012-06-16 02:55:13 +08:00
|
|
|
BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5);
|
2011-01-05 07:09:33 +08:00
|
|
|
|
|
|
|
/* PLL is protected by panel, make sure we can write it */
|
|
|
|
if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
|
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
|
|
|
|
|
|
|
reg = DPLL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
val |= DPLL_VCO_ENABLE;
|
|
|
|
|
|
|
|
/* We do this three times for luck */
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150); /* wait for warmup */
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150); /* wait for warmup */
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150); /* wait for warmup */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
/* Don't disable pipe A or pipe A PLLs if needed */
|
|
|
|
if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Make sure the pipe isn't still relying on us */
|
|
|
|
assert_pipe_disabled(dev_priv, pipe);
|
|
|
|
|
|
|
|
reg = DPLL(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
val &= ~DPLL_VCO_ENABLE;
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
}
|
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
|
|
|
|
{
|
|
|
|
u32 port_mask;
|
|
|
|
|
|
|
|
if (!port)
|
|
|
|
port_mask = DPLL_PORTB_READY_MASK;
|
|
|
|
else
|
|
|
|
port_mask = DPLL_PORTC_READY_MASK;
|
|
|
|
|
|
|
|
if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
|
|
|
|
WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
|
|
|
|
'B' + port, I915_READ(DPLL(0)));
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:34 +08:00
|
|
|
/**
|
2012-11-01 04:12:38 +08:00
|
|
|
* ironlake_enable_pch_pll - enable PCH PLL
|
2011-01-05 07:09:34 +08:00
|
|
|
* @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.
|
|
|
|
*/
|
2012-11-01 04:12:38 +08:00
|
|
|
static void ironlake_enable_pch_pll(struct intel_crtc *intel_crtc)
|
2011-01-05 07:09:34 +08:00
|
|
|
{
|
2012-04-21 00:11:53 +08:00
|
|
|
struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
|
2012-05-14 03:16:12 +08:00
|
|
|
struct intel_pch_pll *pll;
|
2011-01-05 07:09:34 +08:00
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
2012-05-14 03:16:12 +08:00
|
|
|
/* PCH PLLs only available on ILK, SNB and IVB */
|
2011-01-05 07:09:34 +08:00
|
|
|
BUG_ON(dev_priv->info->gen < 5);
|
2012-05-14 03:16:12 +08:00
|
|
|
pll = intel_crtc->pch_pll;
|
|
|
|
if (pll == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (WARN_ON(pll->refcount == 0))
|
|
|
|
return;
|
2012-04-21 00:11:53 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n",
|
|
|
|
pll->pll_reg, pll->active, pll->on,
|
|
|
|
intel_crtc->base.base.id);
|
2011-01-05 07:09:34 +08:00
|
|
|
|
|
|
|
/* PCH refclock must be enabled first */
|
|
|
|
assert_pch_refclk_enabled(dev_priv);
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
if (pll->active++ && pll->on) {
|
2012-05-21 01:10:50 +08:00
|
|
|
assert_pch_pll_enabled(dev_priv, pll, NULL);
|
2012-04-21 00:11:53 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("enabling PCH PLL %x\n", pll->pll_reg);
|
|
|
|
|
|
|
|
reg = pll->pll_reg;
|
2011-01-05 07:09:34 +08:00
|
|
|
val = I915_READ(reg);
|
|
|
|
val |= DPLL_VCO_ENABLE;
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(200);
|
2012-04-21 00:11:53 +08:00
|
|
|
|
|
|
|
pll->on = true;
|
2011-01-05 07:09:34 +08:00
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
|
2011-01-05 07:09:34 +08:00
|
|
|
{
|
2012-04-21 00:11:53 +08:00
|
|
|
struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
|
|
|
|
struct intel_pch_pll *pll = intel_crtc->pch_pll;
|
2011-01-05 07:09:34 +08:00
|
|
|
int reg;
|
2012-04-21 00:11:53 +08:00
|
|
|
u32 val;
|
2011-09-03 03:52:11 +08:00
|
|
|
|
2011-01-05 07:09:34 +08:00
|
|
|
/* PCH only available on ILK+ */
|
|
|
|
BUG_ON(dev_priv->info->gen < 5);
|
2012-04-21 00:11:53 +08:00
|
|
|
if (pll == NULL)
|
|
|
|
return;
|
2011-01-05 07:09:34 +08:00
|
|
|
|
2012-05-14 03:16:12 +08:00
|
|
|
if (WARN_ON(pll->refcount == 0))
|
|
|
|
return;
|
2011-11-16 02:28:53 +08:00
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n",
|
|
|
|
pll->pll_reg, pll->active, pll->on,
|
|
|
|
intel_crtc->base.base.id);
|
2011-11-16 02:28:53 +08:00
|
|
|
|
2012-05-14 03:16:12 +08:00
|
|
|
if (WARN_ON(pll->active == 0)) {
|
2012-05-21 01:10:50 +08:00
|
|
|
assert_pch_pll_disabled(dev_priv, pll, NULL);
|
2012-05-14 03:16:12 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
if (--pll->active) {
|
2012-05-21 01:10:50 +08:00
|
|
|
assert_pch_pll_enabled(dev_priv, pll, NULL);
|
2011-11-16 02:28:53 +08:00
|
|
|
return;
|
2012-04-21 00:11:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg);
|
|
|
|
|
|
|
|
/* Make sure transcoder isn't still depending on us */
|
2013-05-03 17:49:46 +08:00
|
|
|
assert_pch_transcoder_disabled(dev_priv, intel_crtc->pipe);
|
2011-11-16 02:28:53 +08:00
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
reg = pll->pll_reg;
|
2011-01-05 07:09:34 +08:00
|
|
|
val = I915_READ(reg);
|
|
|
|
val &= ~DPLL_VCO_ENABLE;
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(200);
|
2012-04-21 00:11:53 +08:00
|
|
|
|
|
|
|
pll->on = false;
|
2011-01-05 07:09:34 +08:00
|
|
|
}
|
|
|
|
|
2012-11-01 04:12:42 +08:00
|
|
|
static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
2011-01-04 04:14:26 +08:00
|
|
|
{
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
2012-02-15 03:07:09 +08:00
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
uint32_t reg, val, pipeconf_val;
|
2011-01-04 04:14:26 +08:00
|
|
|
|
|
|
|
/* PCH only available on ILK+ */
|
|
|
|
BUG_ON(dev_priv->info->gen < 5);
|
|
|
|
|
|
|
|
/* Make sure PCH DPLL is enabled */
|
2012-05-21 01:10:50 +08:00
|
|
|
assert_pch_pll_enabled(dev_priv,
|
|
|
|
to_intel_crtc(crtc)->pch_pll,
|
|
|
|
to_intel_crtc(crtc));
|
2011-01-04 04:14:26 +08:00
|
|
|
|
|
|
|
/* FDI must be feeding us bits for PCH ports */
|
|
|
|
assert_fdi_tx_enabled(dev_priv, pipe);
|
|
|
|
assert_fdi_rx_enabled(dev_priv, pipe);
|
|
|
|
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
/* Workaround: Set the timing override bit before enabling the
|
|
|
|
* pch transcoder. */
|
|
|
|
reg = TRANS_CHICKEN2(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
|
|
|
I915_WRITE(reg, val);
|
2012-05-10 02:37:19 +08:00
|
|
|
}
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
reg = PCH_TRANSCONF(pipe);
|
2011-01-04 04:14:26 +08:00
|
|
|
val = I915_READ(reg);
|
2012-02-04 03:47:15 +08:00
|
|
|
pipeconf_val = I915_READ(PIPECONF(pipe));
|
2011-06-25 03:19:20 +08:00
|
|
|
|
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
|
/*
|
|
|
|
* make the BPC in transcoder be consistent with
|
|
|
|
* that in pipeconf reg.
|
|
|
|
*/
|
2012-12-17 18:21:38 +08:00
|
|
|
val &= ~PIPECONF_BPC_MASK;
|
|
|
|
val |= pipeconf_val & PIPECONF_BPC_MASK;
|
2011-06-25 03:19:20 +08:00
|
|
|
}
|
2012-02-04 03:47:15 +08:00
|
|
|
|
|
|
|
val &= ~TRANS_INTERLACE_MASK;
|
|
|
|
if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
|
2012-02-15 03:07:09 +08:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev) &&
|
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO))
|
|
|
|
val |= TRANS_LEGACY_INTERLACED_ILK;
|
|
|
|
else
|
|
|
|
val |= TRANS_INTERLACED;
|
2012-02-04 03:47:15 +08:00
|
|
|
else
|
|
|
|
val |= TRANS_PROGRESSIVE;
|
|
|
|
|
2011-01-04 04:14:26 +08:00
|
|
|
I915_WRITE(reg, val | TRANS_ENABLE);
|
|
|
|
if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
|
2013-04-17 22:48:50 +08:00
|
|
|
DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
|
2011-01-04 04:14:26 +08:00
|
|
|
}
|
|
|
|
|
2012-11-01 04:12:43 +08:00
|
|
|
static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
2012-11-01 04:12:47 +08:00
|
|
|
enum transcoder cpu_transcoder)
|
2011-01-04 04:14:26 +08:00
|
|
|
{
|
2012-11-01 04:12:43 +08:00
|
|
|
u32 val, pipeconf_val;
|
|
|
|
|
|
|
|
/* PCH only available on ILK+ */
|
|
|
|
BUG_ON(dev_priv->info->gen < 5);
|
|
|
|
|
|
|
|
/* FDI must be feeding us bits for PCH ports */
|
2012-11-30 05:18:51 +08:00
|
|
|
assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
|
2012-11-01 04:12:47 +08:00
|
|
|
assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
|
2012-11-01 04:12:43 +08:00
|
|
|
|
2012-11-01 04:12:52 +08:00
|
|
|
/* Workaround: set timing override bit. */
|
|
|
|
val = I915_READ(_TRANSA_CHICKEN2);
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
2012-11-01 04:12:52 +08:00
|
|
|
I915_WRITE(_TRANSA_CHICKEN2, val);
|
|
|
|
|
2012-11-01 04:12:49 +08:00
|
|
|
val = TRANS_ENABLE;
|
2012-11-01 04:12:47 +08:00
|
|
|
pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
|
2012-11-01 04:12:43 +08:00
|
|
|
|
2012-11-01 04:12:48 +08:00
|
|
|
if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
|
|
|
|
PIPECONF_INTERLACED_ILK)
|
2012-11-01 04:12:45 +08:00
|
|
|
val |= TRANS_INTERLACED;
|
2012-11-01 04:12:43 +08:00
|
|
|
else
|
|
|
|
val |= TRANS_PROGRESSIVE;
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
I915_WRITE(LPT_TRANSCONF, val);
|
|
|
|
if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100))
|
2012-11-01 04:12:47 +08:00
|
|
|
DRM_ERROR("Failed to enable PCH transcoder\n");
|
2012-11-01 04:12:43 +08:00
|
|
|
}
|
|
|
|
|
2012-11-01 04:12:42 +08:00
|
|
|
static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
2011-01-04 04:14:26 +08:00
|
|
|
{
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
uint32_t reg, val;
|
2011-01-04 04:14:26 +08:00
|
|
|
|
|
|
|
/* FDI relies on the transcoder */
|
|
|
|
assert_fdi_tx_disabled(dev_priv, pipe);
|
|
|
|
assert_fdi_rx_disabled(dev_priv, pipe);
|
|
|
|
|
2011-02-03 04:28:03 +08:00
|
|
|
/* Ports must be off as well */
|
|
|
|
assert_pch_ports_disabled(dev_priv, pipe);
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
reg = PCH_TRANSCONF(pipe);
|
2011-01-04 04:14:26 +08:00
|
|
|
val = I915_READ(reg);
|
|
|
|
val &= ~TRANS_ENABLE;
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
/* wait for PCH transcoder off, transcoder state */
|
|
|
|
if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
|
2013-04-17 22:48:50 +08:00
|
|
|
DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
|
|
|
|
if (!HAS_PCH_IBX(dev)) {
|
|
|
|
/* Workaround: Clear the timing override chicken bit again. */
|
|
|
|
reg = TRANS_CHICKEN2(pipe);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
}
|
2011-01-04 04:14:26 +08:00
|
|
|
}
|
|
|
|
|
2012-11-01 04:12:55 +08:00
|
|
|
static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
|
2012-11-01 04:12:43 +08:00
|
|
|
{
|
|
|
|
u32 val;
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
val = I915_READ(LPT_TRANSCONF);
|
2012-11-01 04:12:43 +08:00
|
|
|
val &= ~TRANS_ENABLE;
|
2013-05-03 17:49:46 +08:00
|
|
|
I915_WRITE(LPT_TRANSCONF, val);
|
2012-11-01 04:12:43 +08:00
|
|
|
/* wait for PCH transcoder off, transcoder state */
|
2013-05-03 17:49:46 +08:00
|
|
|
if (wait_for((I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE) == 0, 50))
|
2012-11-01 04:12:51 +08:00
|
|
|
DRM_ERROR("Failed to disable PCH transcoder\n");
|
2012-11-01 04:12:52 +08:00
|
|
|
|
|
|
|
/* Workaround: clear timing override bit. */
|
|
|
|
val = I915_READ(_TRANSA_CHICKEN2);
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
|
2012-11-01 04:12:52 +08:00
|
|
|
I915_WRITE(_TRANSA_CHICKEN2, val);
|
2011-01-04 04:14:26 +08:00
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
/**
|
2011-01-28 21:54:53 +08:00
|
|
|
* intel_enable_pipe - enable a pipe, asserting requirements
|
2011-01-05 07:09:30 +08:00
|
|
|
* @dev_priv: i915 private structure
|
|
|
|
* @pipe: pipe to enable
|
2011-01-04 04:14:26 +08:00
|
|
|
* @pch_port: on ILK+, is this pipe driving a PCH port or not
|
2011-01-05 07:09:30 +08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2011-01-04 04:14:26 +08:00
|
|
|
static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|
|
|
bool pch_port)
|
2011-01-05 07:09:30 +08:00
|
|
|
{
|
2012-10-24 04:29:59 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
pipe);
|
2012-11-30 05:18:51 +08:00
|
|
|
enum pipe pch_transcoder;
|
2011-01-05 07:09:30 +08:00
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
2013-04-11 22:29:09 +08:00
|
|
|
assert_planes_disabled(dev_priv, pipe);
|
|
|
|
assert_sprites_disabled(dev_priv, pipe);
|
|
|
|
|
2012-12-06 21:12:38 +08:00
|
|
|
if (HAS_PCH_LPT(dev_priv->dev))
|
2012-11-20 23:27:37 +08:00
|
|
|
pch_transcoder = TRANSCODER_A;
|
|
|
|
else
|
|
|
|
pch_transcoder = pipe;
|
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
if (!HAS_PCH_SPLIT(dev_priv->dev))
|
|
|
|
assert_pll_enabled(dev_priv, pipe);
|
2011-01-04 04:14:26 +08:00
|
|
|
else {
|
|
|
|
if (pch_port) {
|
|
|
|
/* if driving the PCH, we need FDI enabled */
|
2012-11-20 23:27:37 +08:00
|
|
|
assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
|
2012-11-30 05:18:51 +08:00
|
|
|
assert_fdi_tx_pll_enabled(dev_priv,
|
|
|
|
(enum pipe) cpu_transcoder);
|
2011-01-04 04:14:26 +08:00
|
|
|
}
|
|
|
|
/* FIXME: assert CPU port conditions for SNB+ */
|
|
|
|
}
|
2011-01-05 07:09:30 +08:00
|
|
|
|
2012-10-24 04:29:59 +08:00
|
|
|
reg = PIPECONF(cpu_transcoder);
|
2011-01-05 07:09:30 +08:00
|
|
|
val = I915_READ(reg);
|
2011-03-17 15:18:29 +08:00
|
|
|
if (val & PIPECONF_ENABLE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
I915_WRITE(reg, val | PIPECONF_ENABLE);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_wait_for_vblank(dev_priv->dev, pipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-01-28 21:54:53 +08:00
|
|
|
* intel_disable_pipe - disable a pipe, asserting requirements
|
2011-01-05 07:09:30 +08:00
|
|
|
* @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.
|
|
|
|
*/
|
|
|
|
static void intel_disable_pipe(struct drm_i915_private *dev_priv,
|
|
|
|
enum pipe pipe)
|
|
|
|
{
|
2012-10-24 04:29:59 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
pipe);
|
2011-01-05 07:09:30 +08:00
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure planes won't keep trying to pump pixels to us,
|
|
|
|
* or we might hang the display.
|
|
|
|
*/
|
|
|
|
assert_planes_disabled(dev_priv, pipe);
|
2013-03-29 00:55:38 +08:00
|
|
|
assert_sprites_disabled(dev_priv, pipe);
|
2011-01-05 07:09:30 +08:00
|
|
|
|
|
|
|
/* Don't disable pipe A or pipe A PLLs if needed */
|
|
|
|
if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
|
|
|
|
return;
|
|
|
|
|
2012-10-24 04:29:59 +08:00
|
|
|
reg = PIPECONF(cpu_transcoder);
|
2011-01-05 07:09:30 +08:00
|
|
|
val = I915_READ(reg);
|
2011-03-17 15:18:29 +08:00
|
|
|
if ((val & PIPECONF_ENABLE) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
I915_WRITE(reg, val & ~PIPECONF_ENABLE);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_wait_for_pipe_off(dev_priv->dev, pipe);
|
|
|
|
}
|
|
|
|
|
2011-07-29 05:47:14 +08:00
|
|
|
/*
|
|
|
|
* Plane regs are double buffered, going from enabled->disabled needs a
|
|
|
|
* trigger in order to latch. The display address reg provides this.
|
|
|
|
*/
|
2012-04-19 02:29:25 +08:00
|
|
|
void intel_flush_display_plane(struct drm_i915_private *dev_priv,
|
2011-07-29 05:47:14 +08:00
|
|
|
enum plane plane)
|
|
|
|
{
|
2012-10-29 23:24:49 +08:00
|
|
|
if (dev_priv->info->gen >= 4)
|
|
|
|
I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane)));
|
|
|
|
else
|
|
|
|
I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
|
2011-07-29 05:47:14 +08:00
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static void intel_enable_plane(struct drm_i915_private *dev_priv,
|
|
|
|
enum plane plane, enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
/* If the pipe isn't enabled, we can't pump pixels and may hang */
|
|
|
|
assert_pipe_enabled(dev_priv, pipe);
|
|
|
|
|
|
|
|
reg = DSPCNTR(plane);
|
|
|
|
val = I915_READ(reg);
|
2011-03-17 15:18:29 +08:00
|
|
|
if (val & DISPLAY_PLANE_ENABLE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
|
2011-07-29 05:47:14 +08:00
|
|
|
intel_flush_display_plane(dev_priv, plane);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_wait_for_vblank(dev_priv->dev, pipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static void intel_disable_plane(struct drm_i915_private *dev_priv,
|
|
|
|
enum plane plane, enum pipe pipe)
|
|
|
|
{
|
|
|
|
int reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
reg = DSPCNTR(plane);
|
|
|
|
val = I915_READ(reg);
|
2011-03-17 15:18:29 +08:00
|
|
|
if ((val & DISPLAY_PLANE_ENABLE) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_flush_display_plane(dev_priv, plane);
|
|
|
|
intel_wait_for_vblank(dev_priv->dev, pipe);
|
|
|
|
}
|
|
|
|
|
2013-03-05 22:52:39 +08:00
|
|
|
static bool need_vtd_wa(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_INTEL_IOMMU
|
|
|
|
if (INTEL_INFO(dev)->gen >= 6 && intel_iommu_gfx_mapped)
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-24 06:32:05 +08:00
|
|
|
int
|
2010-09-14 19:50:34 +08:00
|
|
|
intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj,
|
2010-11-12 21:42:53 +08:00
|
|
|
struct intel_ring_buffer *pipelined)
|
2009-11-19 00:25:18 +08:00
|
|
|
{
|
2011-02-21 22:43:56 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2009-11-19 00:25:18 +08:00
|
|
|
u32 alignment;
|
|
|
|
int ret;
|
|
|
|
|
2010-11-09 03:18:58 +08:00
|
|
|
switch (obj->tiling_mode) {
|
2009-11-19 00:25:18 +08:00
|
|
|
case I915_TILING_NONE:
|
2010-07-06 01:01:46 +08:00
|
|
|
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
|
|
|
|
alignment = 128 * 1024;
|
2010-09-17 07:32:17 +08:00
|
|
|
else if (INTEL_INFO(dev)->gen >= 4)
|
2010-07-06 01:01:46 +08:00
|
|
|
alignment = 4 * 1024;
|
|
|
|
else
|
|
|
|
alignment = 64 * 1024;
|
2009-11-19 00:25:18 +08:00
|
|
|
break;
|
|
|
|
case I915_TILING_X:
|
|
|
|
/* pin() will align the object as required by fence */
|
|
|
|
alignment = 0;
|
|
|
|
break;
|
|
|
|
case I915_TILING_Y:
|
2013-04-07 05:54:56 +08:00
|
|
|
/* 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");
|
2009-11-19 00:25:18 +08:00
|
|
|
return -EINVAL;
|
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
2013-03-05 22:52:39 +08:00
|
|
|
/* 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 (need_vtd_wa(dev) && alignment < 256 * 1024)
|
|
|
|
alignment = 256 * 1024;
|
|
|
|
|
2011-02-21 22:43:56 +08:00
|
|
|
dev_priv->mm.interruptible = false;
|
2011-04-14 16:41:17 +08:00
|
|
|
ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
|
2010-09-14 19:50:34 +08:00
|
|
|
if (ret)
|
2011-02-21 22:43:56 +08:00
|
|
|
goto err_interruptible;
|
2009-11-19 00:25:18 +08:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2012-04-17 22:31:24 +08:00
|
|
|
ret = i915_gem_object_get_fence(obj);
|
2012-03-22 23:10:00 +08:00
|
|
|
if (ret)
|
|
|
|
goto err_unpin;
|
2011-12-14 20:57:08 +08:00
|
|
|
|
2012-03-22 23:10:00 +08:00
|
|
|
i915_gem_object_pin_fence(obj);
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2011-02-21 22:43:56 +08:00
|
|
|
dev_priv->mm.interruptible = true;
|
2009-11-19 00:25:18 +08:00
|
|
|
return 0;
|
2010-09-14 19:50:34 +08:00
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
i915_gem_object_unpin(obj);
|
2011-02-21 22:43:56 +08:00
|
|
|
err_interruptible:
|
|
|
|
dev_priv->mm.interruptible = true;
|
2010-09-14 19:50:34 +08:00
|
|
|
return ret;
|
2009-11-19 00:25:18 +08:00
|
|
|
}
|
|
|
|
|
2011-12-14 20:57:08 +08:00
|
|
|
void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
i915_gem_object_unpin_fence(obj);
|
|
|
|
i915_gem_object_unpin(obj);
|
|
|
|
}
|
|
|
|
|
2012-07-05 18:17:30 +08:00
|
|
|
/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
|
|
|
|
* is assumed to be a power-of-two. */
|
2013-02-22 04:04:31 +08:00
|
|
|
unsigned long intel_gen4_compute_page_offset(int *x, int *y,
|
|
|
|
unsigned int tiling_mode,
|
|
|
|
unsigned int cpp,
|
|
|
|
unsigned int pitch)
|
2012-07-05 18:17:30 +08:00
|
|
|
{
|
2013-02-22 04:04:31 +08:00
|
|
|
if (tiling_mode != I915_TILING_NONE) {
|
|
|
|
unsigned int tile_rows, tiles;
|
2012-07-05 18:17:30 +08:00
|
|
|
|
2013-02-22 04:04:31 +08:00
|
|
|
tile_rows = *y / 8;
|
|
|
|
*y %= 8;
|
2012-07-05 18:17:30 +08:00
|
|
|
|
2013-02-22 04:04:31 +08:00
|
|
|
tiles = *x / (512/cpp);
|
|
|
|
*x %= 512/cpp;
|
|
|
|
|
|
|
|
return tile_rows * pitch * 8 + tiles * 4096;
|
|
|
|
} else {
|
|
|
|
unsigned int offset;
|
|
|
|
|
|
|
|
offset = *y * pitch + *x * cpp;
|
|
|
|
*y = 0;
|
|
|
|
*x = (offset & 4095) / cpp;
|
|
|
|
return offset & -4096;
|
|
|
|
}
|
2012-07-05 18:17:30 +08:00
|
|
|
}
|
|
|
|
|
2011-06-25 03:19:23 +08:00
|
|
|
static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
|
int x, int y)
|
2010-08-03 03:07:50 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_framebuffer *intel_fb;
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj;
|
2010-08-03 03:07:50 +08:00
|
|
|
int plane = intel_crtc->plane;
|
2012-07-05 18:17:29 +08:00
|
|
|
unsigned long linear_offset;
|
2010-08-03 03:07:50 +08:00
|
|
|
u32 dspcntr;
|
2010-09-11 20:48:45 +08:00
|
|
|
u32 reg;
|
2010-08-03 03:07:50 +08:00
|
|
|
|
|
|
|
switch (plane) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
|
2010-08-03 03:07:50 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_fb = to_intel_framebuffer(fb);
|
|
|
|
obj = intel_fb->obj;
|
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = DSPCNTR(plane);
|
|
|
|
dspcntr = I915_READ(reg);
|
2010-08-03 03:07:50 +08:00
|
|
|
/* Mask out pixel format bits in case we change it */
|
|
|
|
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
|
2012-10-31 23:50:14 +08:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
case DRM_FORMAT_C8:
|
2010-08-03 03:07:50 +08:00
|
|
|
dspcntr |= DISPPLANE_8BPP;
|
|
|
|
break;
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_XRGB1555:
|
|
|
|
case DRM_FORMAT_ARGB1555:
|
|
|
|
dspcntr |= DISPPLANE_BGRX555;
|
2010-08-03 03:07:50 +08:00
|
|
|
break;
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
dspcntr |= DISPPLANE_BGRX565;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
|
|
|
dspcntr |= DISPPLANE_BGRX888;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
dspcntr |= DISPPLANE_RGBX888;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
|
|
|
dspcntr |= DISPPLANE_BGRX101010;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
|
dspcntr |= DISPPLANE_RGBX101010;
|
2010-08-03 03:07:50 +08:00
|
|
|
break;
|
|
|
|
default:
|
2013-03-27 07:45:00 +08:00
|
|
|
BUG();
|
2010-08-03 03:07:50 +08:00
|
|
|
}
|
2012-10-31 23:50:14 +08:00
|
|
|
|
2010-09-17 07:32:17 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2010-11-09 03:18:58 +08:00
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
2010-08-03 03:07:50 +08:00
|
|
|
dspcntr |= DISPPLANE_TILED;
|
|
|
|
else
|
|
|
|
dspcntr &= ~DISPPLANE_TILED;
|
|
|
|
}
|
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, dspcntr);
|
2010-08-03 03:07:50 +08:00
|
|
|
|
2012-07-05 18:17:29 +08:00
|
|
|
linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
|
2010-08-03 03:07:50 +08:00
|
|
|
|
2012-07-05 18:17:30 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
intel_crtc->dspaddr_offset =
|
2013-02-22 04:04:31 +08:00
|
|
|
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
|
|
|
|
fb->bits_per_pixel / 8,
|
|
|
|
fb->pitches[0]);
|
2012-07-05 18:17:30 +08:00
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
|
|
|
} else {
|
2012-07-05 18:17:29 +08:00
|
|
|
intel_crtc->dspaddr_offset = linear_offset;
|
2012-07-05 18:17:30 +08:00
|
|
|
}
|
2012-07-05 18:17:29 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
|
|
|
|
obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
|
2011-12-20 06:06:49 +08:00
|
|
|
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
2010-09-17 07:32:17 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2012-07-05 18:17:30 +08:00
|
|
|
I915_MODIFY_DISPBASE(DSPSURF(plane),
|
|
|
|
obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
|
2012-07-05 18:17:29 +08:00
|
|
|
I915_WRITE(DSPLINOFF(plane), linear_offset);
|
2010-09-11 20:48:45 +08:00
|
|
|
} else
|
2012-07-05 18:17:29 +08:00
|
|
|
I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset);
|
2010-09-11 20:48:45 +08:00
|
|
|
POSTING_READ(reg);
|
2010-08-03 03:07:50 +08:00
|
|
|
|
2011-06-25 03:19:23 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ironlake_update_plane(struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb, int x, int y)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_framebuffer *intel_fb;
|
|
|
|
struct drm_i915_gem_object *obj;
|
|
|
|
int plane = intel_crtc->plane;
|
2012-07-05 18:17:29 +08:00
|
|
|
unsigned long linear_offset;
|
2011-06-25 03:19:23 +08:00
|
|
|
u32 dspcntr;
|
|
|
|
u32 reg;
|
|
|
|
|
|
|
|
switch (plane) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
2011-09-03 03:54:37 +08:00
|
|
|
case 2:
|
2011-06-25 03:19:23 +08:00
|
|
|
break;
|
|
|
|
default:
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_ERROR("Can't update plane %c in SAREA\n", plane_name(plane));
|
2011-06-25 03:19:23 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_fb = to_intel_framebuffer(fb);
|
|
|
|
obj = intel_fb->obj;
|
|
|
|
|
|
|
|
reg = DSPCNTR(plane);
|
|
|
|
dspcntr = I915_READ(reg);
|
|
|
|
/* Mask out pixel format bits in case we change it */
|
|
|
|
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
|
2012-10-31 23:50:14 +08:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
case DRM_FORMAT_C8:
|
2011-06-25 03:19:23 +08:00
|
|
|
dspcntr |= DISPPLANE_8BPP;
|
|
|
|
break;
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
dspcntr |= DISPPLANE_BGRX565;
|
2011-06-25 03:19:23 +08:00
|
|
|
break;
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
|
|
|
dspcntr |= DISPPLANE_BGRX888;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
dspcntr |= DISPPLANE_RGBX888;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
|
|
|
dspcntr |= DISPPLANE_BGRX101010;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
|
dspcntr |= DISPPLANE_RGBX101010;
|
2011-06-25 03:19:23 +08:00
|
|
|
break;
|
|
|
|
default:
|
2013-03-27 07:45:00 +08:00
|
|
|
BUG();
|
2011-06-25 03:19:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
|
|
|
dspcntr |= DISPPLANE_TILED;
|
|
|
|
else
|
|
|
|
dspcntr &= ~DISPPLANE_TILED;
|
|
|
|
|
|
|
|
/* must disable */
|
|
|
|
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
|
|
|
|
|
I915_WRITE(reg, dspcntr);
|
|
|
|
|
2012-07-05 18:17:29 +08:00
|
|
|
linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
|
2012-07-05 18:17:30 +08:00
|
|
|
intel_crtc->dspaddr_offset =
|
2013-02-22 04:04:31 +08:00
|
|
|
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
|
|
|
|
fb->bits_per_pixel / 8,
|
|
|
|
fb->pitches[0]);
|
2012-07-05 18:17:30 +08:00
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
2011-06-25 03:19:23 +08:00
|
|
|
|
2012-07-05 18:17:29 +08:00
|
|
|
DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
|
|
|
|
obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
|
2011-12-20 06:06:49 +08:00
|
|
|
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
2012-07-05 18:17:30 +08:00
|
|
|
I915_MODIFY_DISPBASE(DSPSURF(plane),
|
|
|
|
obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2012-10-29 20:14:21 +08:00
|
|
|
if (IS_HASWELL(dev)) {
|
|
|
|
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
|
|
|
|
} else {
|
|
|
|
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
|
|
|
|
I915_WRITE(DSPLINOFF(plane), linear_offset);
|
|
|
|
}
|
2011-06-25 03:19:23 +08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assume fb object is pinned & idle & fenced and just update base pointers */
|
|
|
|
static int
|
|
|
|
intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
|
int x, int y, enum mode_set_atomic state)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
2012-04-17 22:08:19 +08:00
|
|
|
if (dev_priv->display.disable_fbc)
|
|
|
|
dev_priv->display.disable_fbc(dev);
|
2010-08-21 03:40:52 +08:00
|
|
|
intel_increase_pllclock(crtc);
|
2010-08-03 03:07:50 +08:00
|
|
|
|
2012-04-17 22:08:19 +08:00
|
|
|
return dev_priv->display.update_plane(crtc, fb, x, y);
|
2010-08-03 03:07:50 +08:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:08:49 +08:00
|
|
|
void intel_display_handle_reset(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
enum plane plane = intel_crtc->plane;
|
|
|
|
|
|
|
|
intel_prepare_page_flip(dev, plane);
|
|
|
|
intel_finish_page_flip_plane(dev, plane);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
mutex_lock(&crtc->mutex);
|
|
|
|
if (intel_crtc->active)
|
|
|
|
dev_priv->display.update_plane(crtc, crtc->fb,
|
|
|
|
crtc->x, crtc->y);
|
|
|
|
mutex_unlock(&crtc->mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-04 00:58:35 +08:00
|
|
|
static int
|
|
|
|
intel_finish_fb(struct drm_framebuffer *old_fb)
|
|
|
|
{
|
|
|
|
struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
|
|
|
|
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
|
|
|
bool was_interruptible = dev_priv->mm.interruptible;
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
dev_priv->mm.interruptible = false;
|
|
|
|
ret = i915_gem_object_finish_gpu(obj);
|
|
|
|
dev_priv->mm.interruptible = was_interruptible;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-10-31 23:50:24 +08:00
|
|
|
static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_master_private *master_priv;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
if (!dev->primary->master)
|
|
|
|
return;
|
|
|
|
|
|
|
|
master_priv = dev->primary->master->driver_priv;
|
|
|
|
if (!master_priv->sarea_priv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (intel_crtc->pipe) {
|
|
|
|
case 0:
|
|
|
|
master_priv->sarea_priv->pipeA_x = x;
|
|
|
|
master_priv->sarea_priv->pipeA_y = y;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
master_priv->sarea_priv->pipeB_x = x;
|
|
|
|
master_priv->sarea_priv->pipeB_y = y;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-11 21:25:09 +08:00
|
|
|
static int
|
2008-12-18 11:14:46 +08:00
|
|
|
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
struct drm_framebuffer *fb)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2012-04-17 22:08:19 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
struct drm_framebuffer *old_fb;
|
2009-02-11 21:25:09 +08:00
|
|
|
int ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
/* no fb bound */
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
if (!fb) {
|
2011-07-20 06:38:56 +08:00
|
|
|
DRM_ERROR("No FB bound\n");
|
2009-02-11 21:25:09 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-14 05:05:41 +08:00
|
|
|
if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) {
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n",
|
|
|
|
plane_name(intel_crtc->plane),
|
|
|
|
INTEL_INFO(dev)->num_pipes);
|
2009-02-11 21:25:09 +08:00
|
|
|
return -EINVAL;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2009-02-11 21:25:09 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2010-09-20 22:41:01 +08:00
|
|
|
ret = intel_pin_and_fence_fb_obj(dev,
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
to_intel_framebuffer(fb)->obj,
|
2010-11-12 21:42:53 +08:00
|
|
|
NULL);
|
2009-02-11 21:25:09 +08:00
|
|
|
if (ret != 0) {
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2011-07-20 06:38:56 +08:00
|
|
|
DRM_ERROR("pin & fence failed\n");
|
2009-02-11 21:25:09 +08:00
|
|
|
return ret;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
ret = dev_priv->display.update_plane(crtc, fb, x, y);
|
2010-08-08 20:20:19 +08:00
|
|
|
if (ret) {
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
|
2009-02-11 21:25:09 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2011-07-20 06:38:56 +08:00
|
|
|
DRM_ERROR("failed to update base address\n");
|
2010-08-08 20:20:19 +08:00
|
|
|
return ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2008-12-18 11:14:46 +08:00
|
|
|
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
old_fb = crtc->fb;
|
|
|
|
crtc->fb = fb;
|
2012-09-11 03:58:30 +08:00
|
|
|
crtc->x = x;
|
|
|
|
crtc->y = y;
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
|
2010-12-15 00:09:31 +08:00
|
|
|
if (old_fb) {
|
2013-06-02 23:23:01 +08:00
|
|
|
if (intel_crtc->active && old_fb != fb)
|
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
2011-12-14 20:57:08 +08:00
|
|
|
intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
|
2010-12-15 00:09:31 +08:00
|
|
|
}
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-04-17 22:08:19 +08:00
|
|
|
intel_update_fbc(dev);
|
2009-02-11 21:25:09 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-10-31 23:50:24 +08:00
|
|
|
intel_crtc_update_sarea_pos(crtc, x, y);
|
2009-02-11 21:25:09 +08:00
|
|
|
|
|
|
|
return 0;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 16:38:08 +08:00
|
|
|
static void intel_fdi_normal_train(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
u32 reg, temp;
|
|
|
|
|
|
|
|
/* enable normal train */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2011-05-18 07:13:52 +08:00
|
|
|
if (IS_IVYBRIDGE(dev)) {
|
2011-04-29 06:09:55 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE_IVB;
|
|
|
|
temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
|
2011-05-18 07:13:52 +08:00
|
|
|
} else {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
|
2011-04-29 06:09:55 +08:00
|
|
|
}
|
2010-10-28 16:38:08 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_NORMAL_CPT;
|
|
|
|
} else {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_NONE;
|
|
|
|
}
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
|
|
|
|
|
|
|
|
/* wait one idle pattern time */
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(1000);
|
2011-04-29 06:09:55 +08:00
|
|
|
|
|
|
|
/* IVB wants error correction enabled */
|
|
|
|
if (IS_IVYBRIDGE(dev))
|
|
|
|
I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE |
|
|
|
|
FDI_FE_ERRC_ENABLE);
|
2010-10-28 16:38:08 +08:00
|
|
|
}
|
|
|
|
|
2013-02-20 05:31:57 +08:00
|
|
|
static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder;
|
|
|
|
}
|
|
|
|
|
2012-10-27 21:58:40 +08:00
|
|
|
static void ivb_modeset_global_resources(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *pipe_B_crtc =
|
|
|
|
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
|
|
|
|
struct intel_crtc *pipe_C_crtc =
|
|
|
|
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
|
|
|
|
uint32_t temp;
|
|
|
|
|
2013-02-20 05:31:57 +08:00
|
|
|
/*
|
|
|
|
* 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) &&
|
|
|
|
!pipe_has_enabled_pch(pipe_C_crtc)) {
|
2012-10-27 21:58:40 +08:00
|
|
|
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
|
|
|
|
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
temp = I915_READ(SOUTH_CHICKEN1);
|
|
|
|
temp &= ~FDI_BC_BIFURCATION_SELECT;
|
|
|
|
DRM_DEBUG_KMS("disabling fdi C rx\n");
|
|
|
|
I915_WRITE(SOUTH_CHICKEN1, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
/* The FDI link training functions for ILK/Ibexpeak. */
|
|
|
|
static void ironlake_fdi_link_train(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2011-01-05 07:09:37 +08:00
|
|
|
int plane = intel_crtc->plane;
|
2010-09-11 20:48:45 +08:00
|
|
|
u32 reg, temp, tries;
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2011-01-05 07:09:37 +08:00
|
|
|
/* FDI needs bits from pipe & plane first */
|
|
|
|
assert_pipe_enabled(dev_priv, pipe);
|
|
|
|
assert_plane_enabled(dev_priv, plane);
|
|
|
|
|
2010-06-26 03:32:14 +08:00
|
|
|
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
|
for train result */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_IMR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-06-26 03:32:14 +08:00
|
|
|
temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
|
temp &= ~FDI_RX_BIT_LOCK;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
I915_READ(reg);
|
2010-06-26 03:32:14 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2013-04-30 01:33:42 +08:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2010-10-08 07:01:15 +08:00
|
|
|
/* Ironlake workaround, enable clock pointer after FDI enable*/
|
2012-11-01 05:52:28 +08:00
|
|
|
I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
|
|
|
|
I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
|
|
|
|
FDI_RX_PHASE_SYNC_POINTER_EN);
|
2010-10-08 07:01:15 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_IIR(pipe);
|
2010-06-26 03:32:14 +08:00
|
|
|
for (tries = 0; tries < 5; tries++) {
|
2010-09-11 20:48:45 +08:00
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
|
|
if ((temp & FDI_RX_BIT_LOCK)) {
|
|
|
|
DRM_DEBUG_KMS("FDI train 1 done.\n");
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
|
2010-04-07 16:15:54 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-06-26 03:32:14 +08:00
|
|
|
if (tries == 5)
|
2010-09-11 20:48:45 +08:00
|
|
|
DRM_ERROR("FDI train 1 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
/* Train 2 */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_IIR(pipe);
|
2010-06-26 03:32:14 +08:00
|
|
|
for (tries = 0; tries < 5; tries++) {
|
2010-09-11 20:48:45 +08:00
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
|
|
if (temp & FDI_RX_SYMBOL_LOCK) {
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
|
2010-04-07 16:15:54 +08:00
|
|
|
DRM_DEBUG_KMS("FDI train 2 done.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-06-26 03:32:14 +08:00
|
|
|
if (tries == 5)
|
2010-09-11 20:48:45 +08:00
|
|
|
DRM_ERROR("FDI train 2 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_KMS("FDI train done\n");
|
2010-10-08 07:01:11 +08:00
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
static const int snb_b_fdi_train_param[] = {
|
2010-04-07 16:15:54 +08:00
|
|
|
FDI_LINK_TRAIN_400MV_0DB_SNB_B,
|
|
|
|
FDI_LINK_TRAIN_400MV_6DB_SNB_B,
|
|
|
|
FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
|
|
|
|
FDI_LINK_TRAIN_800MV_0DB_SNB_B,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* The FDI link training functions for SNB/Cougarpoint. */
|
|
|
|
static void gen6_fdi_link_train(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2012-03-03 01:53:39 +08:00
|
|
|
u32 reg, temp, i, retry;
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-06-26 03:32:14 +08:00
|
|
|
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
|
for train result */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_IMR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-06-26 03:32:14 +08:00
|
|
|
temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
|
temp &= ~FDI_RX_BIT_LOCK;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-06-26 03:32:14 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2013-04-30 01:33:42 +08:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
/* SNB-B */
|
|
|
|
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2012-10-26 16:58:13 +08:00
|
|
|
I915_WRITE(FDI_RX_MISC(pipe),
|
|
|
|
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
|
|
|
} else {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
|
}
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
for (i = 0; i < 4; i++) {
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= snb_b_fdi_train_param[i];
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(500);
|
|
|
|
|
2012-03-03 01:53:39 +08:00
|
|
|
for (retry = 0; retry < 5; retry++) {
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
if (temp & FDI_RX_BIT_LOCK) {
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
|
|
|
|
DRM_DEBUG_KMS("FDI train 1 done.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
udelay(50);
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
2012-03-03 01:53:39 +08:00
|
|
|
if (retry < 5)
|
|
|
|
break;
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
if (i == 4)
|
2010-09-11 20:48:45 +08:00
|
|
|
DRM_ERROR("FDI train 1 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
/* Train 2 */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
|
if (IS_GEN6(dev)) {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
/* SNB-B */
|
|
|
|
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
|
|
}
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
|
|
|
|
} else {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
|
|
}
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
for (i = 0; i < 4; i++) {
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= snb_b_fdi_train_param[i];
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(500);
|
|
|
|
|
2012-03-03 01:53:39 +08:00
|
|
|
for (retry = 0; retry < 5; retry++) {
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
if (temp & FDI_RX_SYMBOL_LOCK) {
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
|
|
|
|
DRM_DEBUG_KMS("FDI train 2 done.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
udelay(50);
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
2012-03-03 01:53:39 +08:00
|
|
|
if (retry < 5)
|
|
|
|
break;
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
if (i == 4)
|
2010-09-11 20:48:45 +08:00
|
|
|
DRM_ERROR("FDI train 2 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_KMS("FDI train done.\n");
|
|
|
|
}
|
|
|
|
|
2011-04-29 06:09:55 +08:00
|
|
|
/* Manual link training for Ivy Bridge A0 parts */
|
|
|
|
static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
u32 reg, temp, i;
|
|
|
|
|
|
|
|
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
|
for train result */
|
|
|
|
reg = FDI_RX_IMR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
|
temp &= ~FDI_RX_BIT_LOCK;
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150);
|
|
|
|
|
2012-10-27 21:58:40 +08:00
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
|
|
|
|
I915_READ(FDI_RX_IIR(pipe)));
|
|
|
|
|
2011-04-29 06:09:55 +08:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2013-04-30 01:33:42 +08:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
|
2011-04-29 06:09:55 +08:00
|
|
|
temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
2011-10-11 05:28:52 +08:00
|
|
|
temp |= FDI_COMPOSITE_SYNC;
|
2011-04-29 06:09:55 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
|
|
|
|
2012-10-26 16:58:13 +08:00
|
|
|
I915_WRITE(FDI_RX_MISC(pipe),
|
|
|
|
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
|
|
|
|
2011-04-29 06:09:55 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_AUTO;
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
2011-10-11 05:28:52 +08:00
|
|
|
temp |= FDI_COMPOSITE_SYNC;
|
2011-04-29 06:09:55 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150);
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
for (i = 0; i < 4; i++) {
|
2011-04-29 06:09:55 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= snb_b_fdi_train_param[i];
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(500);
|
|
|
|
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
|
|
if (temp & FDI_RX_BIT_LOCK ||
|
|
|
|
(I915_READ(reg) & FDI_RX_BIT_LOCK)) {
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
|
2012-10-27 21:58:40 +08:00
|
|
|
DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i);
|
2011-04-29 06:09:55 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == 4)
|
|
|
|
DRM_ERROR("FDI train 1 fail!\n");
|
|
|
|
|
|
|
|
/* Train 2 */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE_IVB;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(150);
|
|
|
|
|
2011-08-17 03:34:10 +08:00
|
|
|
for (i = 0; i < 4; i++) {
|
2011-04-29 06:09:55 +08:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
|
|
temp |= snb_b_fdi_train_param[i];
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(500);
|
|
|
|
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
|
|
|
|
|
|
if (temp & FDI_RX_SYMBOL_LOCK) {
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
|
2012-10-27 21:58:40 +08:00
|
|
|
DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i);
|
2011-04-29 06:09:55 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == 4)
|
|
|
|
DRM_ERROR("FDI train 2 fail!\n");
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("FDI train done.\n");
|
|
|
|
}
|
|
|
|
|
2012-08-13 01:27:14 +08:00
|
|
|
static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2012-08-13 01:27:14 +08:00
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
2009-06-05 15:38:42 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = intel_crtc->pipe;
|
2010-09-11 20:48:45 +08:00
|
|
|
u32 reg, temp;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-09-11 02:27:03 +08:00
|
|
|
|
2010-09-11 01:57:18 +08:00
|
|
|
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
2013-04-30 01:33:42 +08:00
|
|
|
temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
|
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
|
2012-12-17 18:21:38 +08:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-09-11 01:57:18 +08:00
|
|
|
udelay(200);
|
|
|
|
|
|
|
|
/* Switch from Rawclk to PCDclk */
|
2010-09-11 20:48:45 +08:00
|
|
|
temp = I915_READ(reg);
|
|
|
|
I915_WRITE(reg, temp | FDI_PCDCLK);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-09-11 01:57:18 +08:00
|
|
|
udelay(200);
|
|
|
|
|
2012-11-24 01:30:38 +08:00
|
|
|
/* Enable CPU FDI TX PLL, always on for Ironlake */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
|
|
|
I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
|
2010-09-11 20:48:45 +08:00
|
|
|
|
2012-11-24 01:30:38 +08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(100);
|
2010-09-11 01:26:01 +08:00
|
|
|
}
|
2010-09-11 02:10:00 +08:00
|
|
|
}
|
|
|
|
|
2012-08-13 01:27:14 +08:00
|
|
|
static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
u32 reg, temp;
|
|
|
|
|
|
|
|
/* Switch from PCDclk to Rawclk */
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
I915_WRITE(reg, temp & ~FDI_PCDCLK);
|
|
|
|
|
|
|
|
/* Disable CPU FDI TX PLL */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(100);
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
|
|
|
|
|
|
|
|
/* Wait for the clocks to turn off. */
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(100);
|
|
|
|
}
|
|
|
|
|
2011-01-05 07:09:37 +08:00
|
|
|
static void ironlake_fdi_disable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
u32 reg, temp;
|
|
|
|
|
|
|
|
/* disable CPU FDI tx and PCH FDI rx */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~(0x7 << 16);
|
2012-12-17 18:21:38 +08:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2011-01-05 07:09:37 +08:00
|
|
|
I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(100);
|
|
|
|
|
|
|
|
/* Ironlake workaround, disable clock pointer after downing FDI */
|
2011-01-05 07:09:38 +08:00
|
|
|
if (HAS_PCH_IBX(dev)) {
|
|
|
|
I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
|
|
|
|
}
|
2011-01-05 07:09:37 +08:00
|
|
|
|
|
|
|
/* still set train pattern 1 */
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
|
|
|
} else {
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
|
|
}
|
|
|
|
/* BPC in FDI rx is consistent with that in PIPECONF */
|
|
|
|
temp &= ~(0x07 << 16);
|
2012-12-17 18:21:38 +08:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2011-01-05 07:09:37 +08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
udelay(100);
|
|
|
|
}
|
|
|
|
|
2012-09-28 04:25:58 +08:00
|
|
|
static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-01-30 00:13:34 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-09-28 04:25:58 +08:00
|
|
|
unsigned long flags;
|
|
|
|
bool pending;
|
|
|
|
|
2013-01-30 00:13:34 +08:00
|
|
|
if (i915_reset_in_progress(&dev_priv->gpu_error) ||
|
|
|
|
intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
|
2012-09-28 04:25:58 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
pending = to_intel_crtc(crtc)->unpin_work != NULL;
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
|
|
|
return pending;
|
|
|
|
}
|
|
|
|
|
2010-09-24 06:04:43 +08:00
|
|
|
static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
|
|
|
|
{
|
2012-04-17 17:05:38 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2012-09-28 04:25:58 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-09-24 06:04:43 +08:00
|
|
|
|
|
|
|
if (crtc->fb == NULL)
|
|
|
|
return;
|
|
|
|
|
2012-12-21 04:24:07 +08:00
|
|
|
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
|
|
|
|
|
2012-09-28 04:25:58 +08:00
|
|
|
wait_event(dev_priv->pending_flip_queue,
|
|
|
|
!intel_crtc_has_pending_flip(crtc));
|
|
|
|
|
2012-04-17 17:05:38 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
intel_finish_fb(crtc->fb);
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2010-09-24 06:04:43 +08:00
|
|
|
}
|
|
|
|
|
2012-05-10 02:37:26 +08:00
|
|
|
/* Program iCLKIP clock to the desired frequency */
|
|
|
|
static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
u32 divsel, phaseinc, auxdiv, phasedir = 0;
|
|
|
|
u32 temp;
|
|
|
|
|
2012-12-12 21:06:44 +08:00
|
|
|
mutex_lock(&dev_priv->dpio_lock);
|
|
|
|
|
2012-05-10 02:37:26 +08:00
|
|
|
/* It is necessary to ungate the pixclk gate prior to programming
|
|
|
|
* the divisors, and gate it back when it is done.
|
|
|
|
*/
|
|
|
|
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
|
|
|
|
|
|
|
|
/* Disable SSCCTL */
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL6,
|
2012-12-01 22:04:24 +08:00
|
|
|
intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
|
|
|
|
SBI_SSCCTL_DISABLE,
|
|
|
|
SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
|
|
|
|
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
|
|
|
|
if (crtc->mode.clock == 20000) {
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
u32 iclk_virtual_root_freq = 172800 * 1000;
|
|
|
|
u32 iclk_pi_range = 64;
|
|
|
|
u32 desired_divisor, msb_divisor_value, pi_value;
|
|
|
|
|
|
|
|
desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock);
|
|
|
|
msb_divisor_value = desired_divisor / iclk_pi_range;
|
|
|
|
pi_value = desired_divisor % iclk_pi_range;
|
|
|
|
|
|
|
|
auxdiv = 0;
|
|
|
|
divsel = msb_divisor_value - 2;
|
|
|
|
phaseinc = pi_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This should not happen with any sane values */
|
|
|
|
WARN_ON(SBI_SSCDIVINTPHASE_DIVSEL(divsel) &
|
|
|
|
~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
|
|
|
|
WARN_ON(SBI_SSCDIVINTPHASE_DIR(phasedir) &
|
|
|
|
~SBI_SSCDIVINTPHASE_INCVAL_MASK);
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
|
|
|
|
crtc->mode.clock,
|
|
|
|
auxdiv,
|
|
|
|
divsel,
|
|
|
|
phasedir,
|
|
|
|
phaseinc);
|
|
|
|
|
|
|
|
/* Program SSCDIVINTPHASE6 */
|
2012-12-01 22:04:24 +08:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
|
|
|
|
temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel);
|
|
|
|
temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
|
|
|
|
temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc);
|
|
|
|
temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
|
|
|
|
temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
|
2012-12-01 22:04:24 +08:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
|
|
|
|
/* Program SSCAUXDIV */
|
2012-12-01 22:04:24 +08:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
|
|
|
|
temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
|
2012-12-01 22:04:24 +08:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
|
|
|
|
/* Enable modulator and associated divider */
|
2012-12-01 22:04:24 +08:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
temp &= ~SBI_SSCCTL_DISABLE;
|
2012-12-01 22:04:24 +08:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
|
2012-05-10 02:37:26 +08:00
|
|
|
|
|
|
|
/* Wait for initialization time */
|
|
|
|
udelay(24);
|
|
|
|
|
|
|
|
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
|
2012-12-12 21:06:44 +08:00
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
2012-05-10 02:37:26 +08:00
|
|
|
}
|
|
|
|
|
2013-05-03 17:49:47 +08:00
|
|
|
static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
|
|
|
|
enum pipe pch_transcoder)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
|
|
|
|
|
|
|
|
I915_WRITE(PCH_TRANS_HTOTAL(pch_transcoder),
|
|
|
|
I915_READ(HTOTAL(cpu_transcoder)));
|
|
|
|
I915_WRITE(PCH_TRANS_HBLANK(pch_transcoder),
|
|
|
|
I915_READ(HBLANK(cpu_transcoder)));
|
|
|
|
I915_WRITE(PCH_TRANS_HSYNC(pch_transcoder),
|
|
|
|
I915_READ(HSYNC(cpu_transcoder)));
|
|
|
|
|
|
|
|
I915_WRITE(PCH_TRANS_VTOTAL(pch_transcoder),
|
|
|
|
I915_READ(VTOTAL(cpu_transcoder)));
|
|
|
|
I915_WRITE(PCH_TRANS_VBLANK(pch_transcoder),
|
|
|
|
I915_READ(VBLANK(cpu_transcoder)));
|
|
|
|
I915_WRITE(PCH_TRANS_VSYNC(pch_transcoder),
|
|
|
|
I915_READ(VSYNC(cpu_transcoder)));
|
|
|
|
I915_WRITE(PCH_TRANS_VSYNCSHIFT(pch_transcoder),
|
|
|
|
I915_READ(VSYNCSHIFT(cpu_transcoder)));
|
|
|
|
}
|
|
|
|
|
2011-01-06 02:31:48 +08:00
|
|
|
/*
|
|
|
|
* Enable PCH resources required for PCH ports:
|
|
|
|
* - PCH PLLs
|
|
|
|
* - FDI training & RX/TX
|
|
|
|
* - update transcoder timings
|
|
|
|
* - DP transcoding bits
|
|
|
|
* - transcoder
|
|
|
|
*/
|
|
|
|
static void ironlake_pch_enable(struct drm_crtc *crtc)
|
2010-09-11 02:10:00 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2012-04-21 00:11:53 +08:00
|
|
|
u32 reg, temp;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
assert_pch_transcoder_disabled(dev_priv, pipe);
|
2012-05-11 16:21:25 +08:00
|
|
|
|
2012-10-26 16:58:12 +08:00
|
|
|
/* Write the TU size bits before fdi link training, so that error
|
|
|
|
* detection works. */
|
|
|
|
I915_WRITE(FDI_RX_TUSIZE1(pipe),
|
|
|
|
I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
|
|
|
|
|
2010-09-11 01:57:18 +08:00
|
|
|
/* For PCH output, training FDI link */
|
2011-04-29 05:27:04 +08:00
|
|
|
dev_priv->display.fdi_link_train(crtc);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2012-10-28 00:46:14 +08:00
|
|
|
/* 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. */
|
2012-11-01 04:12:38 +08:00
|
|
|
ironlake_enable_pch_pll(intel_crtc);
|
2012-05-13 16:54:09 +08:00
|
|
|
|
2012-11-01 04:12:23 +08:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
2012-04-21 00:11:53 +08:00
|
|
|
u32 sel;
|
2011-10-13 00:51:31 +08:00
|
|
|
|
2010-09-11 01:57:18 +08:00
|
|
|
temp = I915_READ(PCH_DPLL_SEL);
|
2012-04-21 00:11:53 +08:00
|
|
|
switch (pipe) {
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
temp |= TRANSA_DPLL_ENABLE;
|
|
|
|
sel = TRANSA_DPLLB_SEL;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
temp |= TRANSB_DPLL_ENABLE;
|
|
|
|
sel = TRANSB_DPLLB_SEL;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
temp |= TRANSC_DPLL_ENABLE;
|
|
|
|
sel = TRANSC_DPLLB_SEL;
|
|
|
|
break;
|
2011-10-13 06:01:33 +08:00
|
|
|
}
|
2012-04-21 00:11:53 +08:00
|
|
|
if (intel_crtc->pch_pll->pll_reg == _PCH_DPLL_B)
|
|
|
|
temp |= sel;
|
|
|
|
else
|
|
|
|
temp &= ~sel;
|
2010-09-11 01:57:18 +08:00
|
|
|
I915_WRITE(PCH_DPLL_SEL, temp);
|
|
|
|
}
|
2010-09-11 20:48:45 +08:00
|
|
|
|
2011-01-05 07:09:35 +08:00
|
|
|
/* set transcoder timing, panel must allow it */
|
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
2013-05-03 17:49:47 +08:00
|
|
|
ironlake_pch_transcoder_set_timings(intel_crtc, pipe);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2012-11-01 04:12:23 +08:00
|
|
|
intel_fdi_normal_train(crtc);
|
2010-10-28 16:38:08 +08:00
|
|
|
|
2010-09-11 01:57:18 +08:00
|
|
|
/* For PCH DP, enable TRANS_DP_CTL */
|
|
|
|
if (HAS_PCH_CPT(dev) &&
|
2011-11-02 10:54:11 +08:00
|
|
|
(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
|
2012-12-17 18:21:38 +08:00
|
|
|
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = TRANS_DP_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~(TRANS_DP_PORT_SEL_MASK |
|
2010-11-18 09:32:58 +08:00
|
|
|
TRANS_DP_SYNC_MASK |
|
|
|
|
TRANS_DP_BPC_MASK);
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= (TRANS_DP_OUTPUT_ENABLE |
|
|
|
|
TRANS_DP_ENH_FRAMING);
|
2011-06-25 03:19:21 +08:00
|
|
|
temp |= bpc << 9; /* same format but at 11:9 */
|
2010-09-11 01:57:18 +08:00
|
|
|
|
|
|
|
if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
|
2010-09-11 01:57:18 +08:00
|
|
|
if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
|
2010-09-11 01:57:18 +08:00
|
|
|
|
|
|
|
switch (intel_trans_dp_port_sel(crtc)) {
|
|
|
|
case PCH_DP_B:
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= TRANS_DP_PORT_SEL_B;
|
2010-09-11 01:57:18 +08:00
|
|
|
break;
|
|
|
|
case PCH_DP_C:
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= TRANS_DP_PORT_SEL_C;
|
2010-09-11 01:57:18 +08:00
|
|
|
break;
|
|
|
|
case PCH_DP_D:
|
2010-09-11 20:48:45 +08:00
|
|
|
temp |= TRANS_DP_PORT_SEL_D;
|
2010-09-11 01:57:18 +08:00
|
|
|
break;
|
|
|
|
default:
|
2012-10-26 16:58:16 +08:00
|
|
|
BUG();
|
2009-07-24 01:00:32 +08:00
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
2010-09-11 01:26:01 +08:00
|
|
|
}
|
2010-06-12 14:32:27 +08:00
|
|
|
|
2012-11-01 04:12:42 +08:00
|
|
|
ironlake_enable_pch_transcoder(dev_priv, pipe);
|
2011-01-06 02:31:48 +08:00
|
|
|
}
|
|
|
|
|
2012-11-01 04:12:22 +08:00
|
|
|
static void lpt_pch_enable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-04-18 02:15:07 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
2012-11-01 04:12:22 +08:00
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
|
2012-11-01 04:12:22 +08:00
|
|
|
|
2012-11-01 04:12:24 +08:00
|
|
|
lpt_program_iclkip(crtc);
|
2012-11-01 04:12:22 +08:00
|
|
|
|
2012-11-01 04:12:40 +08:00
|
|
|
/* Set transcoder timing. */
|
2013-05-03 17:49:47 +08:00
|
|
|
ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
|
2012-11-01 04:12:22 +08:00
|
|
|
|
2012-11-01 04:12:47 +08:00
|
|
|
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
|
2011-01-06 02:31:48 +08:00
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
static void intel_put_pch_pll(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
struct intel_pch_pll *pll = intel_crtc->pch_pll;
|
|
|
|
|
|
|
|
if (pll == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pll->refcount == 0) {
|
|
|
|
WARN(1, "bad PCH PLL refcount\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
--pll->refcount;
|
|
|
|
intel_crtc->pch_pll = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
|
|
|
|
struct intel_pch_pll *pll;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
pll = intel_crtc->pch_pll;
|
|
|
|
if (pll) {
|
|
|
|
DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n",
|
|
|
|
intel_crtc->base.base.id, pll->pll_reg);
|
|
|
|
goto prepare;
|
|
|
|
}
|
|
|
|
|
2012-05-21 02:00:25 +08:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
|
/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
|
|
|
|
i = intel_crtc->pipe;
|
|
|
|
pll = &dev_priv->pch_plls[i];
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("CRTC:%d using pre-allocated PCH PLL %x\n",
|
|
|
|
intel_crtc->base.base.id, pll->pll_reg);
|
|
|
|
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
for (i = 0; i < dev_priv->num_pch_pll; i++) {
|
|
|
|
pll = &dev_priv->pch_plls[i];
|
|
|
|
|
|
|
|
/* Only want to check enabled timings first */
|
|
|
|
if (pll->refcount == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) &&
|
|
|
|
fp == I915_READ(pll->fp0_reg)) {
|
|
|
|
DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n",
|
|
|
|
intel_crtc->base.base.id,
|
|
|
|
pll->pll_reg, pll->refcount, pll->active);
|
|
|
|
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ok no matching timings, maybe there's a free one? */
|
|
|
|
for (i = 0; i < dev_priv->num_pch_pll; i++) {
|
|
|
|
pll = &dev_priv->pch_plls[i];
|
|
|
|
if (pll->refcount == 0) {
|
|
|
|
DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n",
|
|
|
|
intel_crtc->base.base.id, pll->pll_reg);
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
found:
|
|
|
|
intel_crtc->pch_pll = pll;
|
|
|
|
pll->refcount++;
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(intel_crtc->pipe));
|
2012-04-21 00:11:53 +08:00
|
|
|
prepare: /* separate function? */
|
|
|
|
DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg);
|
|
|
|
|
2012-05-03 03:43:56 +08:00
|
|
|
/* Wait for the clocks to stabilize before rewriting the regs */
|
|
|
|
I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
|
2012-04-21 00:11:53 +08:00
|
|
|
POSTING_READ(pll->pll_reg);
|
|
|
|
udelay(150);
|
2012-05-03 03:43:56 +08:00
|
|
|
|
|
|
|
I915_WRITE(pll->fp0_reg, fp);
|
|
|
|
I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
|
2012-04-21 00:11:53 +08:00
|
|
|
pll->on = false;
|
|
|
|
return pll;
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:49:50 +08:00
|
|
|
static void cpt_verify_modeset(struct drm_device *dev, int pipe)
|
2011-10-12 01:43:02 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training
has completed and before we enable the transcoder. We also have to
clear that bit again after disabling the pch transcoder.
See "Graphics BSpec: vol4g North Display Engine Registers [IVB],
Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display
Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI
Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31:
"Workaround : Enable the override prior to enabling the transcoder.
Disable the override after disabling the transcoder."
While at it, use the _PIPE macro for the other TRANS_DP register.
v2: Keep the w/a as-is, but kill the original (but wrongly placed)
workaround introduced in
commit 3bcf603f6d5d18bd9d076dc280de71f48add4101
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Wed Jul 27 11:51:40 2011 -0700
drm/i915: apply timing generator bug workaround on CPT and PPT
and
commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue Oct 11 10:43:02 2011 -0700
drm/i915: export a CPT mode set verification function
Note that this old code has unconditionally set the w/a, which might
explain why fdi link training sometimes silently fails, and especially
why the auto-train did not seem to work properly.
v3: Paulo Zanoni pointed out that this workaround is also required on
the LPT PCH. And Arthur Ranyan confirmed that this workaround is
requierd for all ports on the pch, not just DP: The important part
is that the bit is set whenever the pch transcoder is enabled, and
that it is _not_ set while the fdi link is trained. It is also
important that the pch transcoder is fully disabled, i.e. we have to
wait for bit 30 to clear before clearing the w/a bit.
Hence move to workaround into enable/disable_transcoder, where the pch
transcoder gets enabled/disabled.
v4: Whitespace changes dropped.
v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT.
v6:
- resolve conflicts with Paulo's big hsw vga rework
- s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch
to implement the equivalent w/a for LPT is already merged.
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paulo Zanoni <przanoni@gmail.com>
Cc: Arthur Ranyan <arthur.j.runyan@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5)
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-01 16:15:30 +08:00
|
|
|
int dslreg = PIPEDSL(pipe);
|
2011-10-12 01:43:02 +08:00
|
|
|
u32 temp;
|
|
|
|
|
|
|
|
temp = I915_READ(dslreg);
|
|
|
|
udelay(500);
|
|
|
|
if (wait_for(I915_READ(dslreg) != temp, 5)) {
|
|
|
|
if (wait_for(I915_READ(dslreg) != temp, 5))
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_ERROR("mode set failed: pipe %c stuck\n", pipe_name(pipe));
|
2011-10-12 01:43:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-26 03:55:02 +08:00
|
|
|
static void ironlake_pfit_enable(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = crtc->pipe;
|
|
|
|
|
2013-05-04 04:26:37 +08:00
|
|
|
if (crtc->config.pch_pfit.size) {
|
2013-04-26 03:55:02 +08:00
|
|
|
/* Force use of hard-coded filter coefficients
|
|
|
|
* as some pre-programmed values are broken,
|
|
|
|
* e.g. x201.
|
|
|
|
*/
|
|
|
|
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
|
|
|
I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
|
|
|
|
PF_PIPE_SEL_IVB(pipe));
|
|
|
|
else
|
|
|
|
I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
|
|
|
|
I915_WRITE(PF_WIN_POS(pipe), crtc->config.pch_pfit.pos);
|
|
|
|
I915_WRITE(PF_WIN_SZ(pipe), crtc->config.pch_pfit.size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-06 02:31:48 +08:00
|
|
|
static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-06-30 04:40:09 +08:00
|
|
|
struct intel_encoder *encoder;
|
2011-01-06 02:31:48 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
|
|
|
u32 temp;
|
|
|
|
|
2012-07-02 17:43:47 +08:00
|
|
|
WARN_ON(!crtc->enabled);
|
|
|
|
|
2011-01-06 02:31:48 +08:00
|
|
|
if (intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
intel_crtc->active = true;
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
|
|
|
|
|
2011-01-06 02:31:48 +08:00
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
|
|
|
temp = I915_READ(PCH_LVDS);
|
|
|
|
if ((temp & LVDS_PORT_EN) == 0)
|
|
|
|
I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
2012-10-27 21:50:28 +08:00
|
|
|
/* Note: FDI PLL enabling _must_ be done before we enable the
|
|
|
|
* cpu pipes, hence this is separate from all the other fdi/pch
|
|
|
|
* enabling. */
|
2012-08-13 01:27:14 +08:00
|
|
|
ironlake_fdi_pll_enable(intel_crtc);
|
2012-09-07 04:08:33 +08:00
|
|
|
} else {
|
|
|
|
assert_fdi_tx_disabled(dev_priv, pipe);
|
|
|
|
assert_fdi_rx_disabled(dev_priv, pipe);
|
|
|
|
}
|
2011-01-06 02:31:48 +08:00
|
|
|
|
2012-09-07 04:15:40 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
encoder->pre_enable(encoder);
|
2011-01-06 02:31:48 +08:00
|
|
|
|
|
|
|
/* Enable panel fitting for LVDS */
|
2013-04-26 03:55:02 +08:00
|
|
|
ironlake_pfit_enable(intel_crtc);
|
2011-01-06 02:31:48 +08:00
|
|
|
|
2011-06-16 05:32:33 +08:00
|
|
|
/*
|
|
|
|
* On ILK+ LUT must be loaded before the pipe is running but with
|
|
|
|
* clocks enabled
|
|
|
|
*/
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
intel_enable_pipe(dev_priv, pipe,
|
|
|
|
intel_crtc->config.has_pch_encoder);
|
2011-01-06 02:31:48 +08:00
|
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
2011-01-06 02:31:48 +08:00
|
|
|
ironlake_pch_enable(crtc);
|
2010-09-11 01:57:18 +08:00
|
|
|
|
2011-04-26 03:11:50 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2010-09-11 17:47:47 +08:00
|
|
|
intel_update_fbc(dev);
|
2011-04-26 03:11:50 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_crtc_update_cursor(crtc, true);
|
2012-06-30 04:40:09 +08:00
|
|
|
|
2012-07-02 05:24:36 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->enable(encoder);
|
2012-07-02 06:16:19 +08:00
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev))
|
2013-05-03 17:49:50 +08:00
|
|
|
cpt_verify_modeset(dev, intel_crtc->pipe);
|
2012-10-05 01:20:03 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
2010-09-11 01:26:01 +08:00
|
|
|
}
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
/* IPS only exists on ULT machines and is tied to pipe A. */
|
|
|
|
static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
return IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hsw_enable_ips(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
|
|
|
|
|
|
|
if (!crtc->config.ips_enabled)
|
|
|
|
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. */
|
|
|
|
assert_plane_enabled(dev_priv, crtc->plane);
|
|
|
|
I915_WRITE(IPS_CTL, IPS_ENABLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hsw_disable_ips(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
if (!crtc->config.ips_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert_plane_enabled(dev_priv, crtc->plane);
|
|
|
|
I915_WRITE(IPS_CTL, 0);
|
|
|
|
|
|
|
|
/* We need to wait for a vblank before we can disable the plane. */
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
}
|
|
|
|
|
2012-10-24 04:29:51 +08:00
|
|
|
static void haswell_crtc_enable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
|
|
|
|
|
|
|
WARN_ON(!crtc->enabled);
|
|
|
|
|
|
|
|
if (intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
intel_crtc->active = true;
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
|
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
|
|
|
|
|
2012-10-24 04:29:51 +08:00
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
drm/i915: fix Haswell FDI link training code
This commit makes hsw_fdi_link_train responsible for implementing
everything described in the "Enable and train FDI" section from the
Hawell CRT mode set sequence documentation. We completely rewrite
hsw_fdi_link_train to match the documentation and we also call it in
the right place.
This patch was initially sent as a series of tiny patches fixing every
little problem of the function, but since there were too many patches
fixing the same function it got a little difficult to get the "big
picture" of how the function would be in the end, so here we amended
all the patches into a single big patch fixing the whole function.
Problems we fixed:
1 - Train Haswell FDI at the right time.
We need to train the FDI before enabling the pipes and planes, so
we're moving the call from lpt_pch_enable to haswell_crtc_enable
directly.
We are also removing ironlake_fdi_pll_enable since the PLL
enablement on Haswell is completely different and is also done
during the link training steps.
2 - Use the right FDI_RX_CTL register on Haswell
There is only one PCH transcoder, so it's always _FDI_RXA_CTL.
Using "pipe" here is wrong.
3 - Don't rely on DDI_BUF_CTL previous values
Just set the bits we want, everything else is zero. Also
POSTING_READ the register before sleeping.
4 - Program the FDI RX TUSIZE register on hsw_fdi_link_train
According to the mode set sequence documentation, this is the
right place. According to the FDI_RX_TUSIZE register description,
this is the value we should set.
Also remove the code that sets this register from the old
location: lpt_pch_enable.
5 - Properly program FDI_RX_MISC pwrdn lane values on HSW
6 - Wait only 35us for the FDI link training
First we wait 30us for the FDI receiver lane calibration, then we
wait 5us for the FDI auto training time.
7 - Remove an useless indentation level on hsw_fdi_link_train
We already "break" when the link training succeeds.
8 - Disable FDI_RX_ENABLE, not FDI_RX_PLL_ENABLE
When we fail the training.
9 - Change Haswell FDI link training error messages
We shouldn't call DRM_ERROR when still looping through voltage
levels since this is expected and not really a failure. So in this
commit we adjust the error path to only DRM_ERROR when we really
fail after trying everything.
While at it, replace DRM_DEBUG_DRIVER with DRM_DEBUG_KMS since
it's what we use everywhere.
10 - Try each voltage twice at hsw_fdi_link_train
Now with Daniel Vetter's suggestion to use "/2" instead of ">>1".
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
[danvet: Applied tiny bikesheds:
- mention in comment that we test each voltage/emphasis level twice
- realing arguments of the only untouched reg write, it spilled over
the 80 char limit ...]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-11-02 07:00:59 +08:00
|
|
|
dev_priv->display.fdi_link_train(crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
2012-10-24 21:32:00 +08:00
|
|
|
intel_ddi_enable_pipe_clock(intel_crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
2012-10-24 21:32:00 +08:00
|
|
|
/* Enable panel fitting for eDP */
|
2013-04-26 03:55:02 +08:00
|
|
|
ironlake_pfit_enable(intel_crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* On ILK+ LUT must be loaded before the pipe is running but with
|
|
|
|
* clocks enabled
|
|
|
|
*/
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
2012-10-24 21:32:00 +08:00
|
|
|
intel_ddi_set_pipe_settings(crtc);
|
2013-03-07 23:30:27 +08:00
|
|
|
intel_ddi_enable_transcoder_func(crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
intel_enable_pipe(dev_priv, pipe,
|
|
|
|
intel_crtc->config.has_pch_encoder);
|
2012-10-24 04:29:51 +08:00
|
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
hsw_enable_ips(intel_crtc);
|
|
|
|
|
2013-03-27 07:44:55 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
2012-11-01 04:12:22 +08:00
|
|
|
lpt_pch_enable(crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
intel_update_fbc(dev);
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->enable(encoder);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
|
|
|
}
|
|
|
|
|
2013-05-08 16:36:30 +08:00
|
|
|
static void ironlake_pfit_disable(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = crtc->pipe;
|
|
|
|
|
|
|
|
/* 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 (crtc->config.pch_pfit.size) {
|
|
|
|
I915_WRITE(PF_CTL(pipe), 0);
|
|
|
|
I915_WRITE(PF_WIN_POS(pipe), 0);
|
|
|
|
I915_WRITE(PF_WIN_SZ(pipe), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-11 01:26:01 +08:00
|
|
|
static void ironlake_crtc_disable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-06-30 04:40:09 +08:00
|
|
|
struct intel_encoder *encoder;
|
2010-09-11 01:26:01 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
2010-09-11 20:48:45 +08:00
|
|
|
u32 reg, temp;
|
2010-06-12 14:32:27 +08:00
|
|
|
|
2012-06-30 04:40:09 +08:00
|
|
|
|
2010-09-13 21:19:16 +08:00
|
|
|
if (!intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->disable(encoder);
|
|
|
|
|
2010-09-24 06:04:43 +08:00
|
|
|
intel_crtc_wait_for_pending_flips(crtc);
|
2010-09-11 01:26:01 +08:00
|
|
|
drm_vblank_off(dev, pipe);
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_crtc_update_cursor(crtc, false);
|
2010-09-11 20:48:45 +08:00
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_disable_plane(dev_priv, plane, pipe);
|
2010-08-07 18:01:35 +08:00
|
|
|
|
2011-07-08 19:22:37 +08:00
|
|
|
if (dev_priv->cfb_plane == plane)
|
|
|
|
intel_disable_fbc(dev);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_disable_pipe(dev_priv, pipe);
|
2009-07-24 01:00:32 +08:00
|
|
|
|
2013-05-08 16:36:30 +08:00
|
|
|
ironlake_pfit_disable(intel_crtc);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2012-09-07 04:15:40 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->post_disable)
|
|
|
|
encoder->post_disable(encoder);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2011-01-05 07:09:37 +08:00
|
|
|
ironlake_fdi_disable(crtc);
|
2009-07-24 01:00:29 +08:00
|
|
|
|
2012-11-01 04:12:42 +08:00
|
|
|
ironlake_disable_pch_transcoder(dev_priv, pipe);
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
|
2010-08-07 18:01:35 +08:00
|
|
|
|
2010-09-11 01:26:01 +08:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
|
|
|
/* disable TRANS_DP_CTL */
|
2010-09-11 20:48:45 +08:00
|
|
|
reg = TRANS_DP_CTL(pipe);
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
|
2011-02-03 04:08:07 +08:00
|
|
|
temp |= TRANS_DP_PORT_SEL_NONE;
|
2010-09-11 20:48:45 +08:00
|
|
|
I915_WRITE(reg, temp);
|
2010-09-11 01:26:01 +08:00
|
|
|
|
|
|
|
/* disable DPLL_SEL */
|
|
|
|
temp = I915_READ(PCH_DPLL_SEL);
|
2011-02-08 04:26:52 +08:00
|
|
|
switch (pipe) {
|
|
|
|
case 0:
|
2011-10-13 06:01:33 +08:00
|
|
|
temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
|
2011-02-08 04:26:52 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2010-09-11 01:26:01 +08:00
|
|
|
temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
|
2011-02-08 04:26:52 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2011-10-13 00:51:31 +08:00
|
|
|
/* C shares PLL A or B */
|
2011-10-13 06:01:33 +08:00
|
|
|
temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
|
2011-02-08 04:26:52 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BUG(); /* wtf */
|
|
|
|
}
|
2010-09-11 01:26:01 +08:00
|
|
|
I915_WRITE(PCH_DPLL_SEL, temp);
|
|
|
|
}
|
2010-04-08 09:43:27 +08:00
|
|
|
|
2010-09-11 01:26:01 +08:00
|
|
|
/* disable PCH DPLL */
|
2012-04-21 00:11:53 +08:00
|
|
|
intel_disable_pch_pll(intel_crtc);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2012-08-13 01:27:14 +08:00
|
|
|
ironlake_fdi_pll_disable(intel_crtc);
|
2010-09-13 20:54:26 +08:00
|
|
|
|
2010-09-13 21:19:16 +08:00
|
|
|
intel_crtc->active = false;
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_update_watermarks(dev);
|
2011-04-26 03:11:50 +08:00
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_update_fbc(dev);
|
2011-04-26 03:11:50 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2010-09-11 01:26:01 +08:00
|
|
|
}
|
2009-11-25 13:09:38 +08:00
|
|
|
|
2012-10-24 04:29:51 +08:00
|
|
|
static void haswell_crtc_disable(struct drm_crtc *crtc)
|
2012-04-21 00:11:53 +08:00
|
|
|
{
|
2012-10-24 04:29:51 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-04-21 00:11:53 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
2013-04-18 02:15:07 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
2012-04-21 00:11:53 +08:00
|
|
|
|
2012-10-24 04:29:51 +08:00
|
|
|
if (!intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->disable(encoder);
|
|
|
|
|
|
|
|
intel_crtc_wait_for_pending_flips(crtc);
|
|
|
|
drm_vblank_off(dev, pipe);
|
|
|
|
intel_crtc_update_cursor(crtc, false);
|
|
|
|
|
2013-05-07 06:37:36 +08:00
|
|
|
/* FBC must be disabled before disabling the plane on HSW. */
|
2012-10-24 04:29:51 +08:00
|
|
|
if (dev_priv->cfb_plane == plane)
|
|
|
|
intel_disable_fbc(dev);
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
hsw_disable_ips(intel_crtc);
|
|
|
|
|
2013-05-07 06:37:36 +08:00
|
|
|
intel_disable_plane(dev_priv, plane, pipe);
|
|
|
|
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
|
2012-10-24 04:29:51 +08:00
|
|
|
intel_disable_pipe(dev_priv, pipe);
|
|
|
|
|
2012-10-25 02:06:19 +08:00
|
|
|
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
2013-05-08 16:36:30 +08:00
|
|
|
ironlake_pfit_disable(intel_crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
2012-10-24 21:32:00 +08:00
|
|
|
intel_ddi_disable_pipe_clock(intel_crtc);
|
2012-10-24 04:29:51 +08:00
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->post_disable)
|
|
|
|
encoder->post_disable(encoder);
|
|
|
|
|
2013-03-28 17:42:01 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
2012-11-01 04:12:55 +08:00
|
|
|
lpt_disable_pch_transcoder(dev_priv);
|
drm/i915: report Gen5+ CPU and PCH FIFO underruns
In this commit we enable both CPU and PCH FIFO underrun reporting and
start reporting them. We follow a few rules:
- after we receive one of these errors, we mask the interrupt, so
we won't get an "interrupt storm" and we also won't flood dmesg;
- at each mode set we enable the interrupts again, so we'll see each
message at most once per mode set;
- in the specific places where we need to ignore the errors, we
completely mask the interrupts.
The downside of this patch is that since we're completely disabling
(masking) the interrupts instead of just not printing error messages,
we will mask more than just what we want on IVB/HSW CPU interrupts
(due to GEN7_ERR_INT) and on CPT/PPT/LPT PCHs (due to SERR_INT). So
when we decide to mask PCH FIFO underruns for pipe A on CPT, we'll
also be masking PCH FIFO underruns for pipe B, because both are
reported by SERR_INT, which has to be either completely enabled or
completely disabled (in othe words, there's no way to disable/enable
specific bits of GEN7_ERR_INT and SERR_INT).
V2: Rename some functions and variables, downgrade messages to
DRM_DEBUG_DRIVER and rebase.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-13 04:57:57 +08:00
|
|
|
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
|
2012-11-02 07:05:05 +08:00
|
|
|
intel_ddi_fdi_disable(crtc);
|
2012-10-24 04:29:54 +08:00
|
|
|
}
|
2012-10-24 04:29:51 +08:00
|
|
|
|
|
|
|
intel_crtc->active = false;
|
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
intel_update_fbc(dev);
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
static void ironlake_crtc_off(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
intel_put_pch_pll(intel_crtc);
|
|
|
|
}
|
|
|
|
|
2012-10-05 23:05:58 +08:00
|
|
|
static void haswell_crtc_off(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
intel_ddi_put_crtc_pll(crtc);
|
|
|
|
}
|
|
|
|
|
2009-09-16 04:57:34 +08:00
|
|
|
static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
|
|
|
|
{
|
|
|
|
if (!enable && intel_crtc->overlay) {
|
2010-08-12 20:53:37 +08:00
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
2011-02-21 22:43:56 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2009-09-16 04:57:37 +08:00
|
|
|
|
2010-08-12 20:53:37 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2011-02-21 22:43:56 +08:00
|
|
|
dev_priv->mm.interruptible = false;
|
|
|
|
(void) intel_overlay_switch_off(intel_crtc->overlay);
|
|
|
|
dev_priv->mm.interruptible = true;
|
2010-08-12 20:53:37 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2009-09-16 04:57:34 +08:00
|
|
|
}
|
|
|
|
|
2010-08-12 20:50:28 +08:00
|
|
|
/* Let userspace switch the overlay on again. In most cases userspace
|
|
|
|
* has to recompute where to put it anyway.
|
|
|
|
*/
|
2009-09-16 04:57:34 +08:00
|
|
|
}
|
|
|
|
|
2013-03-04 22:24:38 +08:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
|
{
|
|
|
|
u32 cntl = I915_READ(CURCNTR(pipe));
|
|
|
|
|
|
|
|
if ((cntl & CURSOR_MODE) == 0) {
|
|
|
|
u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
|
|
|
|
|
|
|
|
I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
|
|
|
|
I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
|
|
|
|
intel_wait_for_vblank(dev_priv->dev, pipe);
|
|
|
|
I915_WRITE(CURCNTR(pipe), cntl);
|
|
|
|
I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
|
|
|
|
I915_WRITE(FW_BLC_SELF, fw_bcl_self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-26 03:55:01 +08:00
|
|
|
static void i9xx_pfit_enable(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc_config *pipe_config = &crtc->config;
|
|
|
|
|
2013-05-08 16:36:31 +08:00
|
|
|
if (!crtc->config.gmch_pfit.control)
|
2013-04-26 03:55:01 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
2013-05-28 18:05:54 +08:00
|
|
|
* The panel fitter should only be adjusted whilst the pipe is disabled,
|
|
|
|
* according to register description and PRM.
|
2013-04-26 03:55:01 +08:00
|
|
|
*/
|
2013-05-28 18:05:54 +08:00
|
|
|
WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
|
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-04-26 03:55:01 +08:00
|
|
|
|
2013-04-26 03:55:02 +08:00
|
|
|
I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
|
|
|
|
I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
|
2013-04-26 04:52:18 +08:00
|
|
|
|
|
|
|
/* Border color in case we don't scale up to the full screen. Black by
|
|
|
|
* default, change to something else for debugging. */
|
|
|
|
I915_WRITE(BCLRPAT(crtc->pipe), 0);
|
2013-04-26 03:55:01 +08:00
|
|
|
}
|
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
static void valleyview_crtc_enable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
|
|
|
|
|
|
|
WARN_ON(!crtc->enabled);
|
|
|
|
|
|
|
|
if (intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
intel_crtc->active = true;
|
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->dpio_lock);
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
encoder->pre_pll_enable(encoder);
|
|
|
|
|
|
|
|
intel_enable_pll(dev_priv, pipe);
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
|
|
|
/* VLV wants encoder enabling _before_ the pipe is up. */
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->enable(encoder);
|
|
|
|
|
2013-04-26 03:55:01 +08:00
|
|
|
/* Enable panel fitting for eDP */
|
|
|
|
i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
intel_enable_pipe(dev_priv, pipe, false);
|
|
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
|
|
|
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
intel_update_fbc(dev);
|
|
|
|
|
|
|
|
/* Give the overlay scaler a chance to enable if it's on this pipe */
|
|
|
|
intel_crtc_dpms_overlay(intel_crtc, true);
|
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
|
|
|
}
|
|
|
|
|
2010-09-11 01:31:34 +08:00
|
|
|
static void i9xx_crtc_enable(struct drm_crtc *crtc)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-06-30 04:40:09 +08:00
|
|
|
struct intel_encoder *encoder;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
2009-09-11 06:28:06 +08:00
|
|
|
int plane = intel_crtc->plane;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-02 17:43:47 +08:00
|
|
|
WARN_ON(!crtc->enabled);
|
|
|
|
|
2010-09-13 21:19:16 +08:00
|
|
|
if (intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
intel_crtc->active = true;
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
2011-01-05 07:09:33 +08:00
|
|
|
intel_enable_pll(dev_priv, pipe);
|
2013-02-08 22:35:38 +08:00
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
2013-04-26 03:55:01 +08:00
|
|
|
/* Enable panel fitting for LVDS */
|
|
|
|
i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
2011-01-04 04:14:26 +08:00
|
|
|
intel_enable_pipe(dev_priv, pipe, false);
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
2013-03-04 22:24:38 +08:00
|
|
|
if (IS_G4X(dev))
|
|
|
|
g4x_fixup_plane(dev_priv, pipe);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-09-11 01:31:34 +08:00
|
|
|
intel_crtc_load_lut(crtc);
|
2010-09-11 17:47:47 +08:00
|
|
|
intel_update_fbc(dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-09-11 01:31:34 +08:00
|
|
|
/* Give the overlay scaler a chance to enable if it's on this pipe */
|
|
|
|
intel_crtc_dpms_overlay(intel_crtc, true);
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_crtc_update_cursor(crtc, true);
|
2012-06-30 04:40:09 +08:00
|
|
|
|
2012-07-02 05:24:36 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->enable(encoder);
|
2010-09-11 01:31:34 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2013-04-11 22:29:06 +08:00
|
|
|
static void i9xx_pfit_disable(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
2013-05-08 16:36:31 +08:00
|
|
|
if (!crtc->config.gmch_pfit.control)
|
|
|
|
return;
|
2013-04-11 22:29:06 +08:00
|
|
|
|
2013-05-08 16:36:31 +08:00
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-04-11 22:29:06 +08:00
|
|
|
|
2013-05-08 16:36:31 +08:00
|
|
|
DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
|
|
|
|
I915_READ(PFIT_CONTROL));
|
|
|
|
I915_WRITE(PFIT_CONTROL, 0);
|
2013-04-11 22:29:06 +08:00
|
|
|
}
|
|
|
|
|
2010-09-11 01:31:34 +08:00
|
|
|
static void i9xx_crtc_disable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-06-30 04:40:09 +08:00
|
|
|
struct intel_encoder *encoder;
|
2010-09-11 01:31:34 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
2012-06-30 04:40:09 +08:00
|
|
|
|
2010-09-13 21:19:16 +08:00
|
|
|
if (!intel_crtc->active)
|
|
|
|
return;
|
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
encoder->disable(encoder);
|
|
|
|
|
2010-09-11 01:31:34 +08:00
|
|
|
/* Give the overlay scaler a chance to disable if it's on this pipe */
|
2010-09-24 06:04:43 +08:00
|
|
|
intel_crtc_wait_for_pending_flips(crtc);
|
|
|
|
drm_vblank_off(dev, pipe);
|
2010-09-11 01:31:34 +08:00
|
|
|
intel_crtc_dpms_overlay(intel_crtc, false);
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_crtc_update_cursor(crtc, false);
|
2010-09-11 01:31:34 +08:00
|
|
|
|
2011-07-08 19:22:37 +08:00
|
|
|
if (dev_priv->cfb_plane == plane)
|
|
|
|
intel_disable_fbc(dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-01-05 07:09:30 +08:00
|
|
|
intel_disable_plane(dev_priv, plane, pipe);
|
|
|
|
intel_disable_pipe(dev_priv, pipe);
|
2013-02-08 22:35:37 +08:00
|
|
|
|
2013-04-11 22:29:06 +08:00
|
|
|
i9xx_pfit_disable(intel_crtc);
|
2013-02-08 22:35:37 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->post_disable)
|
|
|
|
encoder->post_disable(encoder);
|
|
|
|
|
2011-01-05 07:09:33 +08:00
|
|
|
intel_disable_pll(dev_priv, pipe);
|
2010-09-11 01:31:34 +08:00
|
|
|
|
2010-09-13 21:19:16 +08:00
|
|
|
intel_crtc->active = false;
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_update_fbc(dev);
|
|
|
|
intel_update_watermarks(dev);
|
2010-09-11 01:31:34 +08:00
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
static void i9xx_crtc_off(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-07-09 04:34:21 +08:00
|
|
|
static void intel_crtc_update_sarea(struct drm_crtc *crtc,
|
|
|
|
bool enabled)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_master_private *master_priv;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
if (!dev->primary->master)
|
|
|
|
return;
|
|
|
|
|
|
|
|
master_priv = dev->primary->master->driver_priv;
|
|
|
|
if (!master_priv->sarea_priv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (pipe) {
|
|
|
|
case 0:
|
|
|
|
master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
|
|
|
|
master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0;
|
|
|
|
master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
|
|
|
|
break;
|
|
|
|
default:
|
2011-02-08 04:26:52 +08:00
|
|
|
DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-09 04:34:21 +08:00
|
|
|
/**
|
|
|
|
* Sets the power management mode of the pipe and plane.
|
|
|
|
*/
|
|
|
|
void intel_crtc_update_dpms(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
|
bool enable = false;
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
|
|
|
|
enable |= intel_encoder->connectors_active;
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
dev_priv->display.crtc_enable(crtc);
|
|
|
|
else
|
|
|
|
dev_priv->display.crtc_disable(crtc);
|
|
|
|
|
|
|
|
intel_crtc_update_sarea(crtc, enable);
|
|
|
|
}
|
|
|
|
|
2010-09-08 23:30:16 +08:00
|
|
|
static void intel_crtc_disable(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2012-07-09 04:34:21 +08:00
|
|
|
struct drm_connector *connector;
|
2012-04-21 00:11:53 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-01-22 23:25:25 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2010-09-08 23:30:16 +08:00
|
|
|
|
2012-07-09 04:34:21 +08:00
|
|
|
/* crtc should still be enabled when we disable it. */
|
|
|
|
WARN_ON(!crtc->enabled);
|
|
|
|
|
|
|
|
dev_priv->display.crtc_disable(crtc);
|
2013-05-03 23:15:40 +08:00
|
|
|
intel_crtc->eld_vld = false;
|
2012-07-09 04:34:21 +08:00
|
|
|
intel_crtc_update_sarea(crtc, false);
|
2012-04-21 00:11:53 +08:00
|
|
|
dev_priv->display.off(crtc);
|
|
|
|
|
2012-01-17 07:01:13 +08:00
|
|
|
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
|
|
|
|
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
|
2010-09-08 23:30:16 +08:00
|
|
|
|
|
|
|
if (crtc->fb) {
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
2011-12-14 20:57:08 +08:00
|
|
|
intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
|
2010-09-08 23:30:16 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2012-07-09 04:34:21 +08:00
|
|
|
crtc->fb = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update computed state. */
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
|
|
if (!connector->encoder || !connector->encoder->crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (connector->encoder->crtc != crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
connector->dpms = DRM_MODE_DPMS_OFF;
|
|
|
|
to_intel_encoder(connector->encoder)->connectors_active = false;
|
2010-09-08 23:30:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-27 01:21:47 +08:00
|
|
|
void intel_modeset_disable(struct drm_device *dev)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-07-27 01:21:47 +08:00
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
if (crtc->enabled)
|
|
|
|
intel_crtc_disable(crtc);
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-08-04 20:50:23 +08:00
|
|
|
void intel_encoder_destroy(struct drm_encoder *encoder)
|
2010-09-11 01:47:20 +08:00
|
|
|
{
|
2010-09-09 22:14:28 +08:00
|
|
|
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
2010-08-04 20:50:23 +08:00
|
|
|
|
|
|
|
drm_encoder_cleanup(encoder);
|
|
|
|
kfree(intel_encoder);
|
2010-09-11 01:47:20 +08:00
|
|
|
}
|
|
|
|
|
2012-06-30 14:59:56 +08:00
|
|
|
/* 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. */
|
|
|
|
void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
|
2010-09-11 01:47:20 +08:00
|
|
|
{
|
2012-06-30 14:59:56 +08:00
|
|
|
if (mode == DRM_MODE_DPMS_ON) {
|
|
|
|
encoder->connectors_active = true;
|
|
|
|
|
drm/i915: convert dpms functions of dvo/sdvo/crt
Yeah, big patch but I couldn't come up with a neat idea of how to
split it up further, that wouldn't break dpms on cloned configs
somehow. But the changes in dvo/sdvo/crt are all pretty much
orthonogal, so it's not too bad a patch.
These are the only encoders that support cloning, which requires a few
special changes compared to the previous patches.
- Compute the desired state of the display pipe by walking all
connected encoders and checking whether any has active connectors.
To make this clearer, drop the old mode parameter to the crtc dpms
function and rename it to intel_crtc_update_dpms.
- There's the curious case of intel_crtc->dpms_mode. With the previous
patches to remove the overlay pipe A code and to rework the load
detect pipe code, the big users are gone. We still keep it to avoid
enabling the pipe twice, but we duplicate this logic with
crtc->active, too. Still, leave this for now and just push a fake
dpms mode into it that reflects the state of the display pipe.
Changes in the encoder dpms functions:
- We clamp the dpms state to the supported range right away. This is
escpecially important for the VGA outputs, where only older hw
supports the intermediate states. This (and the crt->adpa_reg patch)
allows us to unify the crt dpms code again between all variants
(gmch, vlv and pch).
- We only enable/disable the output for dvo/sdvo and leave the encoder
running. The encoder will be disabled/enabled when we switch the
state of the entire output pipeline (which will happen right away
for non-cloned setups). This way the duplication is reduced and
strange interaction when disabling output ports at the wrong time
avoided.
The dpms code for all three types of connectors contains a bit of
duplicated logic, but I think keeping these special cases separate is
simpler: CRT is the only one that hanldes intermediate dpms state
(which requires extra logic to enable/disable things in the right
order), and introducing some abstraction just to share the code
between dvo and sdvo smells like overkill. We can do that once someone
bothers to implement cloning for the more modern outputs. But I doubt
that this will ever happen.
v2: s/crtc/crt/_set_dpms, noticed by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-02 04:42:24 +08:00
|
|
|
intel_crtc_update_dpms(encoder->base.crtc);
|
2012-06-30 14:59:56 +08:00
|
|
|
} else {
|
|
|
|
encoder->connectors_active = false;
|
|
|
|
|
drm/i915: convert dpms functions of dvo/sdvo/crt
Yeah, big patch but I couldn't come up with a neat idea of how to
split it up further, that wouldn't break dpms on cloned configs
somehow. But the changes in dvo/sdvo/crt are all pretty much
orthonogal, so it's not too bad a patch.
These are the only encoders that support cloning, which requires a few
special changes compared to the previous patches.
- Compute the desired state of the display pipe by walking all
connected encoders and checking whether any has active connectors.
To make this clearer, drop the old mode parameter to the crtc dpms
function and rename it to intel_crtc_update_dpms.
- There's the curious case of intel_crtc->dpms_mode. With the previous
patches to remove the overlay pipe A code and to rework the load
detect pipe code, the big users are gone. We still keep it to avoid
enabling the pipe twice, but we duplicate this logic with
crtc->active, too. Still, leave this for now and just push a fake
dpms mode into it that reflects the state of the display pipe.
Changes in the encoder dpms functions:
- We clamp the dpms state to the supported range right away. This is
escpecially important for the VGA outputs, where only older hw
supports the intermediate states. This (and the crt->adpa_reg patch)
allows us to unify the crt dpms code again between all variants
(gmch, vlv and pch).
- We only enable/disable the output for dvo/sdvo and leave the encoder
running. The encoder will be disabled/enabled when we switch the
state of the entire output pipeline (which will happen right away
for non-cloned setups). This way the duplication is reduced and
strange interaction when disabling output ports at the wrong time
avoided.
The dpms code for all three types of connectors contains a bit of
duplicated logic, but I think keeping these special cases separate is
simpler: CRT is the only one that hanldes intermediate dpms state
(which requires extra logic to enable/disable things in the right
order), and introducing some abstraction just to share the code
between dvo and sdvo smells like overkill. We can do that once someone
bothers to implement cloning for the more modern outputs. But I doubt
that this will ever happen.
v2: s/crtc/crt/_set_dpms, noticed by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-02 04:42:24 +08:00
|
|
|
intel_crtc_update_dpms(encoder->base.crtc);
|
2012-06-30 14:59:56 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-07-03 03:54:27 +08:00
|
|
|
/* Cross check the actual hw state with our own modeset state tracking (and it's
|
|
|
|
* internal consistency). */
|
2012-08-31 23:37:33 +08:00
|
|
|
static void intel_connector_check_state(struct intel_connector *connector)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-07-03 03:54:27 +08:00
|
|
|
if (connector->get_hw_state(connector)) {
|
|
|
|
struct intel_encoder *encoder = connector->encoder;
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
bool encoder_enabled;
|
|
|
|
enum pipe pipe;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
|
|
|
connector->base.base.id,
|
|
|
|
drm_get_connector_name(&connector->base));
|
|
|
|
|
|
|
|
WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
|
|
|
|
"wrong connector dpms state\n");
|
|
|
|
WARN(connector->base.encoder != &encoder->base,
|
|
|
|
"active connector not linked to encoder\n");
|
|
|
|
WARN(!encoder->connectors_active,
|
|
|
|
"encoder->connectors_active not set\n");
|
|
|
|
|
|
|
|
encoder_enabled = encoder->get_hw_state(encoder, &pipe);
|
|
|
|
WARN(!encoder_enabled, "encoder not enabled\n");
|
|
|
|
if (WARN_ON(!encoder->base.crtc))
|
|
|
|
return;
|
|
|
|
|
|
|
|
crtc = encoder->base.crtc;
|
|
|
|
|
|
|
|
WARN(!crtc->enabled, "crtc not enabled\n");
|
|
|
|
WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
|
|
|
|
WARN(pipe != to_intel_crtc(crtc)->pipe,
|
|
|
|
"encoder active on the wrong pipe\n");
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-06-30 14:59:56 +08:00
|
|
|
/* Even simpler default implementation, if there's really no special case to
|
|
|
|
* consider. */
|
|
|
|
void intel_connector_dpms(struct drm_connector *connector, int mode)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-06-30 14:59:56 +08:00
|
|
|
struct intel_encoder *encoder = intel_attached_encoder(connector);
|
2011-10-12 01:43:02 +08:00
|
|
|
|
2012-06-30 14:59:56 +08:00
|
|
|
/* All the simple cases only support two dpms states. */
|
|
|
|
if (mode != DRM_MODE_DPMS_ON)
|
|
|
|
mode = DRM_MODE_DPMS_OFF;
|
2011-10-12 01:43:02 +08:00
|
|
|
|
2012-06-30 14:59:56 +08:00
|
|
|
if (mode == connector->dpms)
|
|
|
|
return;
|
|
|
|
|
|
|
|
connector->dpms = mode;
|
|
|
|
|
|
|
|
/* Only need to change hw state when actually enabled */
|
|
|
|
if (encoder->base.crtc)
|
|
|
|
intel_encoder_dpms(encoder, mode);
|
|
|
|
else
|
2012-07-10 15:50:11 +08:00
|
|
|
WARN_ON(encoder->connectors_active != false);
|
2012-07-03 03:54:27 +08:00
|
|
|
|
2012-08-31 23:37:33 +08:00
|
|
|
intel_modeset_check_state(connector->dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-07-02 19:10:34 +08:00
|
|
|
/* 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. */
|
|
|
|
bool intel_connector_get_hw_state(struct intel_connector *connector)
|
2010-08-04 20:50:23 +08:00
|
|
|
{
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
enum pipe pipe = 0;
|
2012-07-02 19:10:34 +08:00
|
|
|
struct intel_encoder *encoder = connector->encoder;
|
2010-08-04 20:50:23 +08:00
|
|
|
|
2012-07-02 19:10:34 +08:00
|
|
|
return encoder->get_hw_state(encoder, &pipe);
|
2010-08-04 20:50:23 +08:00
|
|
|
}
|
|
|
|
|
2013-04-30 01:34:16 +08:00
|
|
|
static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *pipe_B_crtc =
|
|
|
|
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n",
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
|
|
|
if (pipe_config->fdi_lanes > 4) {
|
|
|
|
DRM_DEBUG_KMS("invalid fdi lane config on pipe %c: %i lanes\n",
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_HASWELL(dev)) {
|
|
|
|
if (pipe_config->fdi_lanes > 2) {
|
|
|
|
DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
|
|
|
|
pipe_config->fdi_lanes);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->num_pipes == 2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Ivybridge 3 pipe is really complicated */
|
|
|
|
switch (pipe) {
|
|
|
|
case PIPE_A:
|
|
|
|
return true;
|
|
|
|
case PIPE_B:
|
|
|
|
if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
|
|
|
|
pipe_config->fdi_lanes > 2) {
|
|
|
|
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
case PIPE_C:
|
2013-02-20 05:31:57 +08:00
|
|
|
if (!pipe_has_enabled_pch(pipe_B_crtc) ||
|
2013-04-30 01:34:16 +08:00
|
|
|
pipe_B_crtc->config.fdi_lanes <= 2) {
|
|
|
|
if (pipe_config->fdi_lanes > 2) {
|
|
|
|
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
#define RETRY 1
|
|
|
|
static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
2013-04-19 17:24:43 +08:00
|
|
|
{
|
2013-04-30 01:34:16 +08:00
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
2013-04-19 17:24:43 +08:00
|
|
|
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
|
|
|
|
int target_clock, lane, link_bw;
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
bool setup_ok, needs_recompute = false;
|
2013-04-19 17:24:43 +08:00
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
retry:
|
2013-04-19 17:24:43 +08:00
|
|
|
/* 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:
|
|
|
|
*/
|
|
|
|
link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
|
|
|
|
|
|
|
|
if (pipe_config->pixel_target_clock)
|
|
|
|
target_clock = pipe_config->pixel_target_clock;
|
|
|
|
else
|
|
|
|
target_clock = adjusted_mode->clock;
|
|
|
|
|
|
|
|
lane = ironlake_get_lanes_required(target_clock, link_bw,
|
|
|
|
pipe_config->pipe_bpp);
|
|
|
|
|
|
|
|
pipe_config->fdi_lanes = lane;
|
|
|
|
|
|
|
|
if (pipe_config->pixel_multiplier > 1)
|
|
|
|
link_bw *= pipe_config->pixel_multiplier;
|
|
|
|
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, target_clock,
|
|
|
|
link_bw, &pipe_config->fdi_m_n);
|
2013-04-30 01:34:16 +08:00
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev,
|
|
|
|
intel_crtc->pipe, pipe_config);
|
|
|
|
if (!setup_ok && pipe_config->pipe_bpp > 6*3) {
|
|
|
|
pipe_config->pipe_bpp -= 2*3;
|
|
|
|
DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
|
|
|
|
pipe_config->pipe_bpp);
|
|
|
|
needs_recompute = true;
|
|
|
|
pipe_config->bw_constrained = true;
|
|
|
|
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needs_recompute)
|
|
|
|
return RETRY;
|
|
|
|
|
|
|
|
return setup_ok ? 0 : -EINVAL;
|
2013-04-19 17:24:43 +08:00
|
|
|
}
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
static void hsw_compute_ips_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
2013-06-01 03:33:23 +08:00
|
|
|
pipe_config->ips_enabled = i915_enable_ips &&
|
|
|
|
hsw_crtc_supports_ips(crtc) &&
|
2013-06-01 03:33:22 +08:00
|
|
|
pipe_config->pipe_bpp == 24;
|
|
|
|
}
|
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
static int intel_crtc_compute_config(struct drm_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2009-06-05 15:38:42 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
|
2013-06-01 03:33:22 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2010-09-13 01:25:19 +08:00
|
|
|
|
2009-10-23 07:11:14 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev)) {
|
2009-06-05 15:38:42 +08:00
|
|
|
/* FDI link clock is fixed at 2.7G */
|
2013-03-27 07:44:50 +08:00
|
|
|
if (pipe_config->requested_mode.clock * 3
|
|
|
|
> IRONLAKE_FDI_FREQ * 4)
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
return -EINVAL;
|
2009-06-05 15:38:42 +08:00
|
|
|
}
|
2010-09-13 01:25:19 +08:00
|
|
|
|
2012-04-16 01:53:19 +08:00
|
|
|
/* 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.*/
|
2013-03-27 07:44:52 +08:00
|
|
|
if (!pipe_config->timings_set)
|
2012-04-16 01:53:19 +08:00
|
|
|
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
2010-09-13 01:25:19 +08:00
|
|
|
|
2013-05-04 01:48:11 +08:00
|
|
|
/* Cantiga+ cannot handle modes with a hsync front porch of 0.
|
|
|
|
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
|
2012-06-21 18:19:59 +08:00
|
|
|
*/
|
|
|
|
if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
|
|
|
|
adjusted_mode->hsync_start == adjusted_mode->hdisplay)
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
return -EINVAL;
|
2012-06-21 18:19:59 +08:00
|
|
|
|
2013-04-18 02:01:39 +08:00
|
|
|
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) {
|
2013-03-27 07:45:01 +08:00
|
|
|
pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */
|
2013-04-18 02:01:39 +08:00
|
|
|
} else if (INTEL_INFO(dev)->gen <= 4 && pipe_config->pipe_bpp > 8*3) {
|
2013-03-27 07:45:01 +08:00
|
|
|
/* only a 8bpc pipe, with 6bpc dither through the panel fitter
|
|
|
|
* for lvds. */
|
|
|
|
pipe_config->pipe_bpp = 8*3;
|
|
|
|
}
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
if (IS_HASWELL(dev))
|
|
|
|
hsw_compute_ips_config(intel_crtc, pipe_config);
|
|
|
|
|
2013-04-19 17:24:43 +08:00
|
|
|
if (pipe_config->has_pch_encoder)
|
2013-06-01 03:33:22 +08:00
|
|
|
return ironlake_fdi_compute_config(intel_crtc, pipe_config);
|
2013-04-19 17:24:43 +08:00
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
return 0;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-03-29 04:39:23 +08:00
|
|
|
static int valleyview_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
return 400000; /* FIXME */
|
|
|
|
}
|
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
static int i945_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
return 400000;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
static int i915_get_display_clock_speed(struct drm_device *dev)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2009-09-22 01:42:27 +08:00
|
|
|
return 333000;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
static int i9xx_misc_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
return 200000;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
static int i915gm_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
u16 gcfgc = 0;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
|
|
|
|
|
|
|
if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
|
|
|
|
return 133000;
|
|
|
|
else {
|
|
|
|
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
|
|
|
|
case GC_DISPLAY_CLOCK_333_MHZ:
|
|
|
|
return 333000;
|
|
|
|
default:
|
|
|
|
case GC_DISPLAY_CLOCK_190_200_MHZ:
|
|
|
|
return 190000;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2009-09-22 01:42:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int i865_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
return 266000;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int i855_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
u16 hpllcc = 0;
|
|
|
|
/* 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:
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
return 133000;
|
2009-09-22 01:42:27 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
/* Shouldn't happen */
|
|
|
|
return 0;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
static int i830_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
return 133000;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2009-06-05 15:38:42 +08:00
|
|
|
static void
|
2013-04-23 20:03:34 +08:00
|
|
|
intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2013-04-23 20:03:34 +08:00
|
|
|
while (*num > DATA_LINK_M_N_MASK ||
|
|
|
|
*den > DATA_LINK_M_N_MASK) {
|
2009-06-05 15:38:42 +08:00
|
|
|
*num >>= 1;
|
|
|
|
*den >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-23 20:03:34 +08:00
|
|
|
static void compute_m_n(unsigned int m, unsigned int n,
|
|
|
|
uint32_t *ret_m, uint32_t *ret_n)
|
|
|
|
{
|
|
|
|
*ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
|
|
|
|
*ret_m = div_u64((uint64_t) m * *ret_n, n);
|
|
|
|
intel_reduce_m_n_ratio(ret_m, ret_n);
|
|
|
|
}
|
|
|
|
|
2012-11-29 22:59:36 +08:00
|
|
|
void
|
|
|
|
intel_link_compute_m_n(int bits_per_pixel, int nlanes,
|
|
|
|
int pixel_clock, int link_clock,
|
|
|
|
struct intel_link_m_n *m_n)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2012-11-29 22:59:36 +08:00
|
|
|
m_n->tu = 64;
|
2013-04-23 20:03:34 +08:00
|
|
|
|
|
|
|
compute_m_n(bits_per_pixel * pixel_clock,
|
|
|
|
link_clock * nlanes * 8,
|
|
|
|
&m_n->gmch_m, &m_n->gmch_n);
|
|
|
|
|
|
|
|
compute_m_n(pixel_clock, link_clock,
|
|
|
|
&m_n->link_m, &m_n->link_n);
|
2009-06-05 15:38:42 +08:00
|
|
|
}
|
|
|
|
|
2011-01-13 01:04:08 +08:00
|
|
|
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
|
|
|
|
{
|
2011-09-27 07:09:45 +08:00
|
|
|
if (i915_panel_use_ssc >= 0)
|
|
|
|
return i915_panel_use_ssc != 0;
|
2013-05-10 07:03:18 +08:00
|
|
|
return dev_priv->vbt.lvds_use_ssc
|
2011-07-13 05:56:22 +08:00
|
|
|
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
|
2011-01-13 01:04:08 +08:00
|
|
|
}
|
|
|
|
|
2012-06-16 02:55:13 +08:00
|
|
|
static int vlv_get_refclk(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int refclk = 27000; /* for DP & HDMI */
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-12-16 04:30:36 +08:00
|
|
|
static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int refclk;
|
|
|
|
|
2012-06-16 02:55:13 +08:00
|
|
|
if (IS_VALLEYVIEW(dev)) {
|
|
|
|
refclk = vlv_get_refclk(crtc);
|
|
|
|
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
2011-12-16 04:30:36 +08:00
|
|
|
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
2013-05-10 07:03:18 +08:00
|
|
|
refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
|
2011-12-16 04:30:36 +08:00
|
|
|
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
|
|
|
refclk / 1000);
|
|
|
|
} else if (!IS_GEN2(dev)) {
|
|
|
|
refclk = 96000;
|
|
|
|
} else {
|
|
|
|
refclk = 48000;
|
|
|
|
}
|
|
|
|
|
|
|
|
return refclk;
|
|
|
|
}
|
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
|
|
|
|
{
|
|
|
|
return (1 << dpll->n) << 16 | dpll->m1 << 8 | dpll->m2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
|
|
|
|
{
|
|
|
|
return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
|
2011-12-16 04:30:37 +08:00
|
|
|
intel_clock_t *reduced_clock)
|
|
|
|
{
|
2013-03-28 17:42:02 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2011-12-16 04:30:37 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-03-28 17:42:02 +08:00
|
|
|
int pipe = crtc->pipe;
|
2011-12-16 04:30:37 +08:00
|
|
|
u32 fp, fp2 = 0;
|
|
|
|
|
|
|
|
if (IS_PINEVIEW(dev)) {
|
2013-04-20 23:19:46 +08:00
|
|
|
fp = pnv_dpll_compute_fp(&crtc->config.dpll);
|
2011-12-16 04:30:37 +08:00
|
|
|
if (reduced_clock)
|
2013-04-20 23:19:46 +08:00
|
|
|
fp2 = pnv_dpll_compute_fp(reduced_clock);
|
2011-12-16 04:30:37 +08:00
|
|
|
} else {
|
2013-04-20 23:19:46 +08:00
|
|
|
fp = i9xx_dpll_compute_fp(&crtc->config.dpll);
|
2011-12-16 04:30:37 +08:00
|
|
|
if (reduced_clock)
|
2013-04-20 23:19:46 +08:00
|
|
|
fp2 = i9xx_dpll_compute_fp(reduced_clock);
|
2011-12-16 04:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
I915_WRITE(FP0(pipe), fp);
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
crtc->lowfreq_avail = false;
|
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
|
2011-12-16 04:30:37 +08:00
|
|
|
reduced_clock && i915_powersave) {
|
|
|
|
I915_WRITE(FP1(pipe), fp2);
|
2013-03-28 17:42:02 +08:00
|
|
|
crtc->lowfreq_avail = true;
|
2011-12-16 04:30:37 +08:00
|
|
|
} else {
|
|
|
|
I915_WRITE(FP1(pipe), fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
|
|
|
|
{
|
|
|
|
u32 reg_val;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PLLB opamp always calibrates to max value of 0x3f, force enable it
|
|
|
|
* and set it to a reasonable value instead.
|
|
|
|
*/
|
2013-05-22 20:36:19 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1));
|
2013-04-19 05:51:36 +08:00
|
|
|
reg_val &= 0xffffff00;
|
|
|
|
reg_val |= 0x00000030;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
2013-05-22 20:36:19 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION);
|
2013-04-19 05:51:36 +08:00
|
|
|
reg_val &= 0x8cffffff;
|
|
|
|
reg_val = 0x8c000000;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
2013-05-22 20:36:19 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1));
|
2013-04-19 05:51:36 +08:00
|
|
|
reg_val &= 0xffffff00;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
2013-05-22 20:36:19 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION);
|
2013-04-19 05:51:36 +08:00
|
|
|
reg_val &= 0x00ffffff;
|
|
|
|
reg_val |= 0xb0000000;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
|
2013-04-19 05:51:36 +08:00
|
|
|
}
|
|
|
|
|
2013-05-03 17:49:48 +08:00
|
|
|
static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
|
|
|
|
struct intel_link_m_n *m_n)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = crtc->pipe;
|
|
|
|
|
2013-05-03 17:49:49 +08:00
|
|
|
I915_WRITE(PCH_TRANS_DATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
|
|
|
|
I915_WRITE(PCH_TRANS_DATA_N1(pipe), m_n->gmch_n);
|
|
|
|
I915_WRITE(PCH_TRANS_LINK_M1(pipe), m_n->link_m);
|
|
|
|
I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n);
|
2013-05-03 17:49:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
|
|
|
|
struct intel_link_m_n *m_n)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
int pipe = crtc->pipe;
|
|
|
|
enum transcoder transcoder = crtc->config.cpu_transcoder;
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 5) {
|
|
|
|
I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
|
|
|
|
I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
|
|
|
|
I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
|
|
|
|
I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
|
|
|
|
} else {
|
2013-05-03 17:49:49 +08:00
|
|
|
I915_WRITE(PIPE_DATA_M_G4X(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
|
|
|
|
I915_WRITE(PIPE_DATA_N_G4X(pipe), m_n->gmch_n);
|
|
|
|
I915_WRITE(PIPE_LINK_M_G4X(pipe), m_n->link_m);
|
|
|
|
I915_WRITE(PIPE_LINK_N_G4X(pipe), m_n->link_n);
|
2013-05-03 17:49:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 05:42:31 +08:00
|
|
|
static void intel_dp_set_m_n(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
if (crtc->config.has_pch_encoder)
|
|
|
|
intel_pch_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
|
|
|
|
else
|
|
|
|
intel_cpu_transcoder_set_m_n(crtc, &crtc->config.dp_m_n);
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
static void vlv_update_pll(struct intel_crtc *crtc)
|
2012-06-16 02:55:13 +08:00
|
|
|
{
|
2013-03-28 17:42:02 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-06-16 02:55:13 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-04-19 05:51:36 +08:00
|
|
|
struct drm_display_mode *adjusted_mode =
|
|
|
|
&crtc->config.adjusted_mode;
|
|
|
|
struct intel_encoder *encoder;
|
2013-03-28 17:42:02 +08:00
|
|
|
int pipe = crtc->pipe;
|
2013-04-19 05:51:36 +08:00
|
|
|
u32 dpll, mdiv;
|
2012-06-16 02:55:13 +08:00
|
|
|
u32 bestn, bestm1, bestm2, bestp1, bestp2;
|
2013-04-19 05:51:36 +08:00
|
|
|
bool is_hdmi;
|
2013-04-19 17:14:37 +08:00
|
|
|
u32 coreclk, reg_val, dpll_md;
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2012-12-12 21:06:44 +08:00
|
|
|
mutex_lock(&dev_priv->dpio_lock);
|
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
is_hdmi = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
bestn = crtc->config.dpll.n;
|
|
|
|
bestm1 = crtc->config.dpll.m1;
|
|
|
|
bestm2 = crtc->config.dpll.m2;
|
|
|
|
bestp1 = crtc->config.dpll.p1;
|
|
|
|
bestp2 = crtc->config.dpll.p2;
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
/* See eDP HDMI DPIO driver vbios notes doc */
|
|
|
|
|
|
|
|
/* PLL B needs special handling */
|
|
|
|
if (pipe)
|
|
|
|
vlv_pllb_recal_opamp(dev_priv);
|
|
|
|
|
|
|
|
/* Set up Tx target for periodic Rcomp update */
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
|
|
|
/* Disable target IRef on PLL */
|
2013-05-22 20:36:19 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF_CTL(pipe));
|
2013-04-19 05:51:36 +08:00
|
|
|
reg_val &= 0x00ffffff;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
|
|
|
/* Disable fast lock */
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610);
|
2013-04-19 05:51:36 +08:00
|
|
|
|
|
|
|
/* Set idtafcrecal before PLL is enabled */
|
2012-06-16 02:55:13 +08:00
|
|
|
mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
|
|
|
|
mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
|
|
|
|
mdiv |= ((bestn << DPIO_N_SHIFT));
|
|
|
|
mdiv |= (1 << DPIO_K_SHIFT);
|
2013-05-03 01:48:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
mdiv |= DPIO_ENABLE_CALIBRATION;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
/* Set HBR and RBR LPF coefficients */
|
|
|
|
if (adjusted_mode->clock == 162000 ||
|
|
|
|
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x005f0021);
|
|
|
|
else
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x00d0000f);
|
|
|
|
|
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
|
|
|
|
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
|
|
|
|
/* Use SSC source */
|
|
|
|
if (!pipe)
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x0df40000);
|
|
|
|
else
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x0df70000);
|
|
|
|
} else { /* HDMI or VGA */
|
|
|
|
/* Use bend source */
|
|
|
|
if (!pipe)
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x0df70000);
|
|
|
|
else
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
|
2013-04-19 05:51:36 +08:00
|
|
|
0x0df40000);
|
|
|
|
}
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-05-22 20:36:19 +08:00
|
|
|
coreclk = vlv_dpio_read(dev_priv, DPIO_CORE_CLK(pipe));
|
2013-04-19 05:51:36 +08:00
|
|
|
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
|
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) ||
|
|
|
|
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))
|
|
|
|
coreclk |= 0x01000000;
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-05-22 20:36:19 +08:00
|
|
|
vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
encoder->pre_pll_enable(encoder);
|
2012-09-27 21:43:06 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
/* Enable DPIO clock input */
|
|
|
|
dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
|
|
|
|
DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
|
|
|
|
if (pipe)
|
|
|
|
dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
2012-09-27 21:43:06 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
dpll |= DPLL_VCO_ENABLE;
|
2012-09-27 21:43:06 +08:00
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
|
udelay(150);
|
2012-06-16 02:55:13 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
|
|
|
|
DRM_ERROR("DPLL %d failed to lock\n", pipe);
|
|
|
|
|
2013-04-19 17:14:37 +08:00
|
|
|
dpll_md = 0;
|
|
|
|
if (crtc->config.pixel_multiplier > 1) {
|
|
|
|
dpll_md = (crtc->config.pixel_multiplier - 1)
|
|
|
|
<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
|
2012-09-27 21:43:06 +08:00
|
|
|
}
|
2013-04-19 17:14:37 +08:00
|
|
|
I915_WRITE(DPLL_MD(pipe), dpll_md);
|
|
|
|
POSTING_READ(DPLL_MD(pipe));
|
2013-03-28 17:42:02 +08:00
|
|
|
|
2013-04-19 05:51:36 +08:00
|
|
|
if (crtc->config.has_dp_encoder)
|
|
|
|
intel_dp_set_m_n(crtc);
|
2012-12-12 21:06:44 +08:00
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
2012-06-16 02:55:13 +08:00
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
static void i9xx_update_pll(struct intel_crtc *crtc,
|
|
|
|
intel_clock_t *reduced_clock,
|
2012-03-29 05:12:16 +08:00
|
|
|
int num_connectors)
|
|
|
|
{
|
2013-03-28 17:42:02 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-03-29 05:12:16 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-11-27 00:22:07 +08:00
|
|
|
struct intel_encoder *encoder;
|
2013-03-28 17:42:02 +08:00
|
|
|
int pipe = crtc->pipe;
|
2012-03-29 05:12:16 +08:00
|
|
|
u32 dpll;
|
|
|
|
bool is_sdvo;
|
2013-03-28 17:42:02 +08:00
|
|
|
struct dpll *clock = &crtc->config.dpll;
|
2012-03-29 05:12:16 +08:00
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
i9xx_update_pll_dividers(crtc, reduced_clock);
|
2012-09-27 21:43:06 +08:00
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) ||
|
|
|
|
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI);
|
2012-03-29 05:12:16 +08:00
|
|
|
|
|
|
|
dpll = DPLL_VGA_MODE_DIS;
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS))
|
2012-03-29 05:12:16 +08:00
|
|
|
dpll |= DPLLB_MODE_LVDS;
|
|
|
|
else
|
|
|
|
dpll |= DPLLB_MODE_DAC_SERIAL;
|
2013-03-27 07:44:53 +08:00
|
|
|
|
2013-04-19 17:14:37 +08:00
|
|
|
if ((crtc->config.pixel_multiplier > 1) &&
|
|
|
|
(IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))) {
|
|
|
|
dpll |= (crtc->config.pixel_multiplier - 1)
|
|
|
|
<< SDVO_MULTIPLIER_SHIFT_HIRES;
|
2012-03-29 05:12:16 +08:00
|
|
|
}
|
2013-04-19 17:14:37 +08:00
|
|
|
|
|
|
|
if (is_sdvo)
|
|
|
|
dpll |= DPLL_DVO_HIGH_SPEED;
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT))
|
2012-03-29 05:12:16 +08:00
|
|
|
dpll |= DPLL_DVO_HIGH_SPEED;
|
|
|
|
|
|
|
|
/* compute bitmask from p1 value */
|
|
|
|
if (IS_PINEVIEW(dev))
|
|
|
|
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
|
|
|
|
else {
|
|
|
|
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
|
|
|
if (IS_G4X(dev) && reduced_clock)
|
|
|
|
dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
|
|
|
}
|
|
|
|
switch (clock->p2) {
|
|
|
|
case 5:
|
|
|
|
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4)
|
|
|
|
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
|
|
|
|
|
2013-04-30 20:01:45 +08:00
|
|
|
if (crtc->config.sdvo_tv_clock)
|
2012-03-29 05:12:16 +08:00
|
|
|
dpll |= PLL_REF_INPUT_TVCLKINBC;
|
2013-03-28 17:42:02 +08:00
|
|
|
else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
|
2012-03-29 05:12:16 +08:00
|
|
|
intel_panel_use_ssc(dev_priv) && num_connectors < 2)
|
|
|
|
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
|
|
|
else
|
|
|
|
dpll |= PLL_REF_INPUT_DREFCLK;
|
|
|
|
|
|
|
|
dpll |= DPLL_VCO_ENABLE;
|
|
|
|
I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
|
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
|
udelay(150);
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
2012-11-27 00:22:07 +08:00
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
encoder->pre_pll_enable(encoder);
|
2012-03-29 05:12:16 +08:00
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
if (crtc->config.has_dp_encoder)
|
|
|
|
intel_dp_set_m_n(crtc);
|
2012-03-29 05:12:16 +08:00
|
|
|
|
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
|
|
|
|
/* Wait for the clocks to stabilize. */
|
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
|
udelay(150);
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2013-04-19 17:14:37 +08:00
|
|
|
u32 dpll_md = 0;
|
|
|
|
if (crtc->config.pixel_multiplier > 1) {
|
|
|
|
dpll_md = (crtc->config.pixel_multiplier - 1)
|
|
|
|
<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
|
2012-03-29 05:12:16 +08:00
|
|
|
}
|
2013-04-19 17:14:37 +08:00
|
|
|
I915_WRITE(DPLL_MD(pipe), dpll_md);
|
2012-03-29 05:12:16 +08:00
|
|
|
} else {
|
|
|
|
/* The pixel multiplier can only be updated once the
|
|
|
|
* DPLL is enabled and the clocks are stable.
|
|
|
|
*
|
|
|
|
* So write it again.
|
|
|
|
*/
|
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
static void i8xx_update_pll(struct intel_crtc *crtc,
|
2012-03-29 05:12:16 +08:00
|
|
|
struct drm_display_mode *adjusted_mode,
|
2013-03-28 17:42:02 +08:00
|
|
|
intel_clock_t *reduced_clock,
|
2012-03-29 05:12:16 +08:00
|
|
|
int num_connectors)
|
|
|
|
{
|
2013-03-28 17:42:02 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-03-29 05:12:16 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-11-27 00:22:07 +08:00
|
|
|
struct intel_encoder *encoder;
|
2013-03-28 17:42:02 +08:00
|
|
|
int pipe = crtc->pipe;
|
2012-03-29 05:12:16 +08:00
|
|
|
u32 dpll;
|
2013-03-28 17:42:02 +08:00
|
|
|
struct dpll *clock = &crtc->config.dpll;
|
2012-03-29 05:12:16 +08:00
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
i9xx_update_pll_dividers(crtc, reduced_clock);
|
2012-09-27 21:43:06 +08:00
|
|
|
|
2012-03-29 05:12:16 +08:00
|
|
|
dpll = DPLL_VGA_MODE_DIS;
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) {
|
2012-03-29 05:12:16 +08:00
|
|
|
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
|
|
|
} else {
|
|
|
|
if (clock->p1 == 2)
|
|
|
|
dpll |= PLL_P1_DIVIDE_BY_TWO;
|
|
|
|
else
|
|
|
|
dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
|
|
|
if (clock->p2 == 4)
|
|
|
|
dpll |= PLL_P2_DIVIDE_BY_4;
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
|
2012-03-29 05:12:16 +08:00
|
|
|
intel_panel_use_ssc(dev_priv) && num_connectors < 2)
|
|
|
|
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
|
|
|
else
|
|
|
|
dpll |= PLL_REF_INPUT_DREFCLK;
|
|
|
|
|
|
|
|
dpll |= DPLL_VCO_ENABLE;
|
|
|
|
I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
|
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
|
udelay(150);
|
|
|
|
|
2013-03-28 17:42:02 +08:00
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
2012-11-27 00:22:07 +08:00
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
encoder->pre_pll_enable(encoder);
|
2012-03-29 05:12:16 +08:00
|
|
|
|
2012-09-11 18:37:55 +08:00
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
|
|
|
|
/* Wait for the clocks to stabilize. */
|
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
|
udelay(150);
|
|
|
|
|
2012-03-29 05:12:16 +08:00
|
|
|
/* The pixel multiplier can only be updated once the
|
|
|
|
* DPLL is enabled and the clocks are stable.
|
|
|
|
*
|
|
|
|
* So write it again.
|
|
|
|
*/
|
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
}
|
|
|
|
|
2012-10-02 05:10:53 +08:00
|
|
|
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
struct drm_display_mode *adjusted_mode)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
2013-04-18 02:15:07 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
2013-05-03 17:49:51 +08:00
|
|
|
uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
|
|
|
|
|
|
|
|
/* We need to be careful not to changed the adjusted mode, for otherwise
|
|
|
|
* the hw state checker will get angry at the mismatch. */
|
|
|
|
crtc_vtotal = adjusted_mode->crtc_vtotal;
|
|
|
|
crtc_vblank_end = adjusted_mode->crtc_vblank_end;
|
2012-10-02 05:10:53 +08:00
|
|
|
|
|
|
|
if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
|
|
|
|
/* the chip adds 2 halflines automatically */
|
2013-05-03 17:49:51 +08:00
|
|
|
crtc_vtotal -= 1;
|
|
|
|
crtc_vblank_end -= 1;
|
2012-10-02 05:10:53 +08:00
|
|
|
vsyncshift = adjusted_mode->crtc_hsync_start
|
|
|
|
- adjusted_mode->crtc_htotal / 2;
|
|
|
|
} else {
|
|
|
|
vsyncshift = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen > 3)
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift);
|
2012-10-02 05:10:53 +08:00
|
|
|
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(HTOTAL(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_hdisplay - 1) |
|
|
|
|
((adjusted_mode->crtc_htotal - 1) << 16));
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(HBLANK(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_hblank_start - 1) |
|
|
|
|
((adjusted_mode->crtc_hblank_end - 1) << 16));
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(HSYNC(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_hsync_start - 1) |
|
|
|
|
((adjusted_mode->crtc_hsync_end - 1) << 16));
|
|
|
|
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(VTOTAL(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_vdisplay - 1) |
|
2013-05-03 17:49:51 +08:00
|
|
|
((crtc_vtotal - 1) << 16));
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(VBLANK(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_vblank_start - 1) |
|
2013-05-03 17:49:51 +08:00
|
|
|
((crtc_vblank_end - 1) << 16));
|
2012-10-24 04:30:02 +08:00
|
|
|
I915_WRITE(VSYNC(cpu_transcoder),
|
2012-10-02 05:10:53 +08:00
|
|
|
(adjusted_mode->crtc_vsync_start - 1) |
|
|
|
|
((adjusted_mode->crtc_vsync_end - 1) << 16));
|
|
|
|
|
2012-10-24 21:34:43 +08:00
|
|
|
/* 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. */
|
|
|
|
if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP &&
|
|
|
|
(pipe == PIPE_B || pipe == PIPE_C))
|
|
|
|
I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
|
|
|
|
|
2012-10-02 05:10:53 +08:00
|
|
|
/* pipesrc controls the size that is scaled from, which should
|
|
|
|
* always be the user's requested size.
|
|
|
|
*/
|
|
|
|
I915_WRITE(PIPESRC(pipe),
|
|
|
|
((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
|
|
|
|
}
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
static void intel_get_pipe_timings(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
tmp = I915_READ(HTOTAL(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
tmp = I915_READ(HBLANK(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
tmp = I915_READ(HSYNC(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
|
|
|
|
tmp = I915_READ(VTOTAL(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
tmp = I915_READ(VBLANK(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
tmp = I915_READ(VSYNC(cpu_transcoder));
|
|
|
|
pipe_config->adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
|
|
|
|
if (I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK) {
|
|
|
|
pipe_config->adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE;
|
|
|
|
pipe_config->adjusted_mode.crtc_vtotal += 1;
|
|
|
|
pipe_config->adjusted_mode.crtc_vblank_end += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = I915_READ(PIPESRC(crtc->pipe));
|
|
|
|
pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1;
|
|
|
|
pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
}
|
|
|
|
|
2013-02-20 01:48:54 +08:00
|
|
|
static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t pipeconf;
|
|
|
|
|
|
|
|
pipeconf = I915_READ(PIPECONF(intel_crtc->pipe));
|
|
|
|
|
|
|
|
if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
|
|
|
|
/* 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?
|
|
|
|
*/
|
|
|
|
if (intel_crtc->config.requested_mode.clock >
|
|
|
|
dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
|
|
|
|
pipeconf |= PIPECONF_DOUBLE_WIDE;
|
|
|
|
else
|
|
|
|
pipeconf &= ~PIPECONF_DOUBLE_WIDE;
|
|
|
|
}
|
|
|
|
|
2013-04-24 20:57:17 +08:00
|
|
|
/* only g4x and later have fancy bpc/dither controls */
|
|
|
|
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
|
|
|
|
pipeconf &= ~(PIPECONF_BPC_MASK |
|
|
|
|
PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
|
|
|
|
|
|
|
|
/* Bspec claims that we can't use dithering for 30bpp pipes. */
|
|
|
|
if (intel_crtc->config.dither && intel_crtc->config.pipe_bpp != 30)
|
|
|
|
pipeconf |= PIPECONF_DITHER_EN |
|
2013-02-20 01:48:54 +08:00
|
|
|
PIPECONF_DITHER_TYPE_SP;
|
|
|
|
|
2013-04-24 20:57:17 +08:00
|
|
|
switch (intel_crtc->config.pipe_bpp) {
|
|
|
|
case 18:
|
|
|
|
pipeconf |= PIPECONF_6BPC;
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
pipeconf |= PIPECONF_8BPC;
|
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
pipeconf |= PIPECONF_10BPC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Case prevented by intel_choose_pipe_bpp_dither. */
|
|
|
|
BUG();
|
2013-02-20 01:48:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HAS_PIPE_CXSR(dev)) {
|
|
|
|
if (intel_crtc->lowfreq_avail) {
|
|
|
|
DRM_DEBUG_KMS("enabling CxSR downclocking\n");
|
|
|
|
pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
|
|
|
|
} else {
|
|
|
|
DRM_DEBUG_KMS("disabling CxSR downclocking\n");
|
|
|
|
pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pipeconf &= ~PIPECONF_INTERLACE_MASK;
|
|
|
|
if (!IS_GEN2(dev) &&
|
|
|
|
intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
|
|
|
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
|
|
|
|
else
|
|
|
|
pipeconf |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
2013-04-02 21:10:09 +08:00
|
|
|
if (IS_VALLEYVIEW(dev)) {
|
|
|
|
if (intel_crtc->config.limited_color_range)
|
|
|
|
pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
|
|
|
|
else
|
|
|
|
pipeconf &= ~PIPECONF_COLOR_RANGE_SELECT;
|
|
|
|
}
|
|
|
|
|
2013-02-20 01:48:54 +08:00
|
|
|
I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
|
|
|
|
POSTING_READ(PIPECONF(intel_crtc->pipe));
|
|
|
|
}
|
|
|
|
|
2011-03-31 04:01:02 +08:00
|
|
|
static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
int x, int y,
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
struct drm_framebuffer *fb)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *adjusted_mode =
|
|
|
|
&intel_crtc->config.adjusted_mode;
|
|
|
|
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
2009-09-11 06:28:06 +08:00
|
|
|
int plane = intel_crtc->plane;
|
2010-03-26 02:48:48 +08:00
|
|
|
int refclk, num_connectors = 0;
|
2009-08-18 04:31:43 +08:00
|
|
|
intel_clock_t clock, reduced_clock;
|
2013-02-20 01:48:54 +08:00
|
|
|
u32 dspcntr;
|
2013-04-30 20:01:44 +08:00
|
|
|
bool ok, has_reduced_clock = false;
|
|
|
|
bool is_lvds = false;
|
2010-09-11 20:48:45 +08:00
|
|
|
struct intel_encoder *encoder;
|
2009-03-18 20:13:27 +08:00
|
|
|
const intel_limit_t *limit;
|
2009-02-11 21:25:09 +08:00
|
|
|
int ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-05 15:50:24 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
2010-09-11 20:48:45 +08:00
|
|
|
switch (encoder->type) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
is_lvds = true;
|
|
|
|
break;
|
|
|
|
}
|
2009-02-14 09:56:52 +08:00
|
|
|
|
2010-03-26 02:48:48 +08:00
|
|
|
num_connectors++;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2011-12-16 04:30:36 +08:00
|
|
|
refclk = i9xx_get_refclk(crtc, num_connectors);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2010-12-15 04:04:54 +08:00
|
|
|
limit = intel_limit(crtc, refclk);
|
2012-01-11 07:09:36 +08:00
|
|
|
ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
|
|
|
|
&clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
if (!ok) {
|
|
|
|
DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
2009-02-11 21:25:09 +08:00
|
|
|
return -EINVAL;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-07-09 15:45:04 +08:00
|
|
|
/* Ensure that the cursor is valid for the new mode before changing... */
|
2010-09-13 20:54:26 +08:00
|
|
|
intel_crtc_update_cursor(crtc, true);
|
2010-07-09 15:45:04 +08:00
|
|
|
|
2010-01-06 22:05:56 +08:00
|
|
|
if (is_lvds && dev_priv->lvds_downclock_avail) {
|
2012-01-11 07:09:36 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* by using the FP0/FP1. In such case we will disable the LVDS
|
|
|
|
* downclock feature.
|
|
|
|
*/
|
2010-01-06 22:05:56 +08:00
|
|
|
has_reduced_clock = limit->find_pll(limit, crtc,
|
2010-09-11 20:48:45 +08:00
|
|
|
dev_priv->lvds_downclock,
|
|
|
|
refclk,
|
2012-01-11 07:09:36 +08:00
|
|
|
&clock,
|
2010-09-11 20:48:45 +08:00
|
|
|
&reduced_clock);
|
2009-03-24 14:02:43 +08:00
|
|
|
}
|
2013-03-28 17:42:02 +08:00
|
|
|
/* Compat-code for transition, will disappear. */
|
|
|
|
if (!intel_crtc->config.clock_set) {
|
|
|
|
intel_crtc->config.dpll.n = clock.n;
|
|
|
|
intel_crtc->config.dpll.m1 = clock.m1;
|
|
|
|
intel_crtc->config.dpll.m2 = clock.m2;
|
|
|
|
intel_crtc->config.dpll.p1 = clock.p1;
|
|
|
|
intel_crtc->config.dpll.p2 = clock.p2;
|
|
|
|
}
|
2009-03-24 14:02:43 +08:00
|
|
|
|
2012-03-29 05:12:16 +08:00
|
|
|
if (IS_GEN2(dev))
|
2013-03-28 17:42:02 +08:00
|
|
|
i8xx_update_pll(intel_crtc, adjusted_mode,
|
2012-09-27 21:43:06 +08:00
|
|
|
has_reduced_clock ? &reduced_clock : NULL,
|
|
|
|
num_connectors);
|
2012-06-16 02:55:13 +08:00
|
|
|
else if (IS_VALLEYVIEW(dev))
|
2013-03-28 17:42:02 +08:00
|
|
|
vlv_update_pll(intel_crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
else
|
2013-03-28 17:42:02 +08:00
|
|
|
i9xx_update_pll(intel_crtc,
|
2012-03-29 05:12:16 +08:00
|
|
|
has_reduced_clock ? &reduced_clock : NULL,
|
2013-04-19 05:51:36 +08:00
|
|
|
num_connectors);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
/* Set up the display plane register */
|
|
|
|
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
|
|
|
|
2013-03-09 02:46:00 +08:00
|
|
|
if (!IS_VALLEYVIEW(dev)) {
|
|
|
|
if (pipe == 0)
|
|
|
|
dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
|
|
|
|
else
|
|
|
|
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-10-02 05:10:53 +08:00
|
|
|
intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
|
2010-09-11 20:48:45 +08:00
|
|
|
|
|
|
|
/* pipesrc and dspsize control the size that is scaled from,
|
|
|
|
* which should always be the user's requested size.
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
*/
|
2011-03-31 04:01:04 +08:00
|
|
|
I915_WRITE(DSPSIZE(plane),
|
|
|
|
((mode->vdisplay - 1) << 16) |
|
|
|
|
(mode->hdisplay - 1));
|
|
|
|
I915_WRITE(DSPPOS(plane), 0);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-02-20 01:48:54 +08:00
|
|
|
i9xx_set_pipeconf(intel_crtc);
|
|
|
|
|
2011-03-31 04:01:02 +08:00
|
|
|
I915_WRITE(DSPCNTR(plane), dspcntr);
|
|
|
|
POSTING_READ(DSPCNTR(plane));
|
|
|
|
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
ret = intel_pipe_set_base(crtc, x, y, fb);
|
2011-03-31 04:01:02 +08:00
|
|
|
|
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
static void i9xx_get_pfit_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
tmp = I915_READ(PFIT_CONTROL);
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
|
|
|
if (crtc->pipe != PIPE_B)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* gen2/3 store dither state in pfit control, needs to match */
|
|
|
|
pipe_config->gmch_pfit.control = tmp & PANEL_8TO6_DITHER_ENABLE;
|
|
|
|
} else {
|
|
|
|
if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp & PFIT_ENABLE))
|
|
|
|
return;
|
|
|
|
|
|
|
|
pipe_config->gmch_pfit.control = I915_READ(PFIT_CONTROL);
|
|
|
|
pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
|
|
|
|
if (INTEL_INFO(dev)->gen < 5)
|
|
|
|
pipe_config->gmch_pfit.lvds_border_bits =
|
|
|
|
I915_READ(LVDS) & LVDS_BORDER_ENABLE;
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
2013-05-22 06:50:22 +08:00
|
|
|
pipe_config->cpu_transcoder = crtc->pipe;
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
tmp = I915_READ(PIPECONF(crtc->pipe));
|
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
return false;
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
i9xx_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-12-01 22:04:25 +08:00
|
|
|
static void ironlake_init_pch_refclk(struct drm_device *dev)
|
2011-08-04 03:59:20 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
|
struct intel_encoder *encoder;
|
2013-03-27 07:33:04 +08:00
|
|
|
u32 val, final;
|
2011-08-04 03:59:20 +08:00
|
|
|
bool has_lvds = false;
|
2011-09-23 03:01:57 +08:00
|
|
|
bool has_cpu_edp = false;
|
|
|
|
bool has_panel = false;
|
2011-09-27 05:29:12 +08:00
|
|
|
bool has_ck505 = false;
|
|
|
|
bool can_ssc = false;
|
2011-08-04 03:59:20 +08:00
|
|
|
|
|
|
|
/* We need to take the global config into account */
|
2011-09-23 03:01:57 +08:00
|
|
|
list_for_each_entry(encoder, &mode_config->encoder_list,
|
|
|
|
base.head) {
|
|
|
|
switch (encoder->type) {
|
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
has_panel = true;
|
|
|
|
has_lvds = true;
|
|
|
|
break;
|
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
|
has_panel = true;
|
2013-05-08 18:14:04 +08:00
|
|
|
if (enc_to_dig_port(&encoder->base)->port == PORT_A)
|
2011-09-23 03:01:57 +08:00
|
|
|
has_cpu_edp = true;
|
|
|
|
break;
|
2011-08-04 03:59:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-27 05:29:12 +08:00
|
|
|
if (HAS_PCH_IBX(dev)) {
|
2013-05-10 07:03:18 +08:00
|
|
|
has_ck505 = dev_priv->vbt.display_clock_mode;
|
2011-09-27 05:29:12 +08:00
|
|
|
can_ssc = has_ck505;
|
|
|
|
} else {
|
|
|
|
has_ck505 = false;
|
|
|
|
can_ssc = true;
|
|
|
|
}
|
|
|
|
|
2013-05-08 18:14:04 +08:00
|
|
|
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
|
|
|
|
has_panel, has_lvds, has_ck505);
|
2011-08-04 03:59:20 +08:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2013-03-27 07:33:04 +08:00
|
|
|
val = I915_READ(PCH_DREF_CONTROL);
|
|
|
|
|
|
|
|
/* As we must carefully and slowly disable/enable each source in turn,
|
|
|
|
* compute the final state we want first and check if we need to
|
|
|
|
* make any changes at all.
|
|
|
|
*/
|
|
|
|
final = val;
|
|
|
|
final &= ~DREF_NONSPREAD_SOURCE_MASK;
|
|
|
|
if (has_ck505)
|
|
|
|
final |= DREF_NONSPREAD_CK505_ENABLE;
|
|
|
|
else
|
|
|
|
final |= DREF_NONSPREAD_SOURCE_ENABLE;
|
|
|
|
|
|
|
|
final &= ~DREF_SSC_SOURCE_MASK;
|
|
|
|
final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
|
|
|
final &= ~DREF_SSC1_ENABLE;
|
|
|
|
|
|
|
|
if (has_panel) {
|
|
|
|
final |= DREF_SSC_SOURCE_ENABLE;
|
|
|
|
|
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc)
|
|
|
|
final |= DREF_SSC1_ENABLE;
|
|
|
|
|
|
|
|
if (has_cpu_edp) {
|
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc)
|
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
|
|
|
else
|
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
|
|
|
} else
|
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
|
|
|
} else {
|
|
|
|
final |= DREF_SSC_SOURCE_DISABLE;
|
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (final == val)
|
|
|
|
return;
|
|
|
|
|
2011-08-04 03:59:20 +08:00
|
|
|
/* Always enable nonspread source */
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_NONSPREAD_SOURCE_MASK;
|
2011-08-04 03:59:20 +08:00
|
|
|
|
2011-09-27 05:29:12 +08:00
|
|
|
if (has_ck505)
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_NONSPREAD_CK505_ENABLE;
|
2011-09-27 05:29:12 +08:00
|
|
|
else
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_NONSPREAD_SOURCE_ENABLE;
|
2011-08-04 03:59:20 +08:00
|
|
|
|
2011-09-23 03:01:57 +08:00
|
|
|
if (has_panel) {
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
|
val |= DREF_SSC_SOURCE_ENABLE;
|
2011-08-04 03:59:20 +08:00
|
|
|
|
2011-09-23 03:01:57 +08:00
|
|
|
/* SSC must be turned on before enabling the CPU output */
|
2011-09-27 05:29:12 +08:00
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
2011-09-23 03:01:57 +08:00
|
|
|
DRM_DEBUG_KMS("Using SSC on panel\n");
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_SSC1_ENABLE;
|
2012-03-31 04:14:05 +08:00
|
|
|
} else
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_SSC1_ENABLE;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
|
|
|
/* Get SSC going before enabling the outputs */
|
2013-03-27 07:33:04 +08:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-23 03:01:57 +08:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
udelay(200);
|
|
|
|
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
2011-08-04 03:59:20 +08:00
|
|
|
|
|
|
|
/* Enable CPU source on CPU attached eDP */
|
2011-09-23 03:01:57 +08:00
|
|
|
if (has_cpu_edp) {
|
2011-09-27 05:29:12 +08:00
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
2011-09-23 03:01:57 +08:00
|
|
|
DRM_DEBUG_KMS("Using SSC on eDP\n");
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
2011-09-23 03:01:57 +08:00
|
|
|
}
|
2011-08-04 03:59:20 +08:00
|
|
|
else
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
2011-09-23 03:01:57 +08:00
|
|
|
} else
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
2013-03-27 07:33:04 +08:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-23 03:01:57 +08:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
udelay(200);
|
|
|
|
} else {
|
|
|
|
DRM_DEBUG_KMS("Disabling SSC entirely\n");
|
|
|
|
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
|
|
|
/* Turn off CPU output */
|
2013-03-27 07:33:04 +08:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
2013-03-27 07:33:04 +08:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-23 03:01:57 +08:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
udelay(200);
|
|
|
|
|
|
|
|
/* Turn off the SSC source */
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
|
val |= DREF_SSC_SOURCE_DISABLE;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
|
|
|
/* Turn off SSC1 */
|
2013-03-27 07:33:04 +08:00
|
|
|
val &= ~DREF_SSC1_ENABLE;
|
2011-09-23 03:01:57 +08:00
|
|
|
|
2013-03-27 07:33:04 +08:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-08-04 03:59:20 +08:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
udelay(200);
|
|
|
|
}
|
2013-03-27 07:33:04 +08:00
|
|
|
|
|
|
|
BUG_ON(val != final);
|
2011-08-04 03:59:20 +08:00
|
|
|
}
|
|
|
|
|
2012-12-01 22:04:25 +08:00
|
|
|
/* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */
|
|
|
|
static void lpt_init_pch_refclk(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
bool has_vga = false;
|
|
|
|
bool is_sdv = false;
|
|
|
|
u32 tmp;
|
|
|
|
|
|
|
|
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
|
|
|
|
switch (encoder->type) {
|
|
|
|
case INTEL_OUTPUT_ANALOG:
|
|
|
|
has_vga = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!has_vga)
|
|
|
|
return;
|
|
|
|
|
2013-01-22 22:33:27 +08:00
|
|
|
mutex_lock(&dev_priv->dpio_lock);
|
|
|
|
|
2012-12-01 22:04:25 +08:00
|
|
|
/* XXX: Rip out SDV support once Haswell ships for real. */
|
|
|
|
if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00)
|
|
|
|
is_sdv = true;
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
|
|
|
|
tmp &= ~SBI_SSCCTL_DISABLE;
|
|
|
|
tmp |= SBI_SSCCTL_PATHALT;
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
|
|
|
|
|
|
|
|
udelay(24);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
|
|
|
|
tmp &= ~SBI_SSCCTL_PATHALT;
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
|
|
|
|
|
|
|
|
if (!is_sdv) {
|
|
|
|
tmp = I915_READ(SOUTH_CHICKEN2);
|
|
|
|
tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
|
|
|
|
I915_WRITE(SOUTH_CHICKEN2, tmp);
|
|
|
|
|
|
|
|
if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) &
|
|
|
|
FDI_MPHY_IOSFSB_RESET_STATUS, 100))
|
|
|
|
DRM_ERROR("FDI mPHY reset assert timeout\n");
|
|
|
|
|
|
|
|
tmp = I915_READ(SOUTH_CHICKEN2);
|
|
|
|
tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
|
|
|
|
I915_WRITE(SOUTH_CHICKEN2, tmp);
|
|
|
|
|
|
|
|
if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) &
|
|
|
|
FDI_MPHY_IOSFSB_RESET_STATUS) == 0,
|
|
|
|
100))
|
|
|
|
DRM_ERROR("FDI mPHY reset de-assert timeout\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
|
|
|
|
tmp &= ~(0xFF << 24);
|
|
|
|
tmp |= (0x12 << 24);
|
|
|
|
intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
if (is_sdv) {
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x800C, SBI_MPHY);
|
|
|
|
tmp |= 0x7FFF;
|
|
|
|
intel_sbi_write(dev_priv, 0x800C, tmp, SBI_MPHY);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY);
|
|
|
|
tmp |= (1 << 11);
|
|
|
|
intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY);
|
|
|
|
tmp |= (1 << 11);
|
|
|
|
intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
if (is_sdv) {
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2038, SBI_MPHY);
|
|
|
|
tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16);
|
|
|
|
intel_sbi_write(dev_priv, 0x2038, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2138, SBI_MPHY);
|
|
|
|
tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16);
|
|
|
|
intel_sbi_write(dev_priv, 0x2138, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x203C, SBI_MPHY);
|
|
|
|
tmp |= (0x3F << 8);
|
|
|
|
intel_sbi_write(dev_priv, 0x203C, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x213C, SBI_MPHY);
|
|
|
|
tmp |= (0x3F << 8);
|
|
|
|
intel_sbi_write(dev_priv, 0x213C, tmp, SBI_MPHY);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY);
|
|
|
|
tmp |= (1 << 24) | (1 << 21) | (1 << 18);
|
|
|
|
intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY);
|
|
|
|
tmp |= (1 << 24) | (1 << 21) | (1 << 18);
|
|
|
|
intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
if (!is_sdv) {
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
|
|
|
|
tmp &= ~(7 << 13);
|
|
|
|
tmp |= (5 << 13);
|
|
|
|
intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
|
|
|
|
tmp &= ~(7 << 13);
|
|
|
|
tmp |= (5 << 13);
|
|
|
|
intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY);
|
|
|
|
tmp &= ~0xFF;
|
|
|
|
tmp |= 0x1C;
|
|
|
|
intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY);
|
|
|
|
tmp &= ~0xFF;
|
|
|
|
tmp |= 0x1C;
|
|
|
|
intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY);
|
|
|
|
tmp &= ~(0xFF << 16);
|
|
|
|
tmp |= (0x1C << 16);
|
|
|
|
intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY);
|
|
|
|
tmp &= ~(0xFF << 16);
|
|
|
|
tmp |= (0x1C << 16);
|
|
|
|
intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
if (!is_sdv) {
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
|
|
|
|
tmp |= (1 << 27);
|
|
|
|
intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
|
|
|
|
tmp |= (1 << 27);
|
|
|
|
intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
|
|
|
|
tmp &= ~(0xF << 28);
|
|
|
|
tmp |= (4 << 28);
|
|
|
|
intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
|
|
|
|
tmp &= ~(0xF << 28);
|
|
|
|
tmp |= (4 << 28);
|
|
|
|
intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ULT uses SBI_GEN0, but ULT doesn't have VGA, so we don't care. */
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK);
|
|
|
|
tmp |= SBI_DBUFF0_ENABLE;
|
|
|
|
intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK);
|
2013-01-22 22:33:27 +08:00
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
2012-12-01 22:04:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize reference clocks when the driver loads
|
|
|
|
*/
|
|
|
|
void intel_init_pch_refclk(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
|
|
|
ironlake_init_pch_refclk(dev);
|
|
|
|
else if (HAS_PCH_LPT(dev))
|
|
|
|
lpt_init_pch_refclk(dev);
|
|
|
|
}
|
|
|
|
|
2011-09-03 04:03:05 +08:00
|
|
|
static int ironlake_get_refclk(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int num_connectors = 0;
|
|
|
|
bool is_lvds = false;
|
|
|
|
|
2012-07-05 15:50:24 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
2011-09-03 04:03:05 +08:00
|
|
|
switch (encoder->type) {
|
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
is_lvds = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
num_connectors++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
|
|
|
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
2013-05-10 07:03:18 +08:00
|
|
|
dev_priv->vbt.lvds_ssc_freq);
|
|
|
|
return dev_priv->vbt.lvds_ssc_freq * 1000;
|
2011-09-03 04:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 120000;
|
|
|
|
}
|
|
|
|
|
2013-04-19 17:24:36 +08:00
|
|
|
static void ironlake_set_pipeconf(struct drm_crtc *crtc)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-09-12 21:06:29 +08:00
|
|
|
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2012-09-12 21:06:29 +08:00
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
val = I915_READ(PIPECONF(pipe));
|
|
|
|
|
2012-12-17 18:21:38 +08:00
|
|
|
val &= ~PIPECONF_BPC_MASK;
|
2013-03-27 07:44:57 +08:00
|
|
|
switch (intel_crtc->config.pipe_bpp) {
|
2012-09-12 21:06:29 +08:00
|
|
|
case 18:
|
2012-12-17 18:21:38 +08:00
|
|
|
val |= PIPECONF_6BPC;
|
2012-09-12 21:06:29 +08:00
|
|
|
break;
|
|
|
|
case 24:
|
2012-12-17 18:21:38 +08:00
|
|
|
val |= PIPECONF_8BPC;
|
2012-09-12 21:06:29 +08:00
|
|
|
break;
|
|
|
|
case 30:
|
2012-12-17 18:21:38 +08:00
|
|
|
val |= PIPECONF_10BPC;
|
2012-09-12 21:06:29 +08:00
|
|
|
break;
|
|
|
|
case 36:
|
2012-12-17 18:21:38 +08:00
|
|
|
val |= PIPECONF_12BPC;
|
2012-09-12 21:06:29 +08:00
|
|
|
break;
|
|
|
|
default:
|
2012-09-21 05:36:03 +08:00
|
|
|
/* Case prevented by intel_choose_pipe_bpp_dither. */
|
|
|
|
BUG();
|
2012-09-12 21:06:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
|
2013-04-25 23:54:44 +08:00
|
|
|
if (intel_crtc->config.dither)
|
2012-09-12 21:06:29 +08:00
|
|
|
val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
|
|
|
|
|
|
|
|
val &= ~PIPECONF_INTERLACE_MASK;
|
2013-04-19 17:24:36 +08:00
|
|
|
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
2012-09-12 21:06:29 +08:00
|
|
|
val |= PIPECONF_INTERLACED_ILK;
|
|
|
|
else
|
|
|
|
val |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
2013-03-27 07:44:56 +08:00
|
|
|
if (intel_crtc->config.limited_color_range)
|
2013-01-17 22:31:28 +08:00
|
|
|
val |= PIPECONF_COLOR_RANGE_SELECT;
|
|
|
|
else
|
|
|
|
val &= ~PIPECONF_COLOR_RANGE_SELECT;
|
|
|
|
|
2012-09-12 21:06:29 +08:00
|
|
|
I915_WRITE(PIPECONF(pipe), val);
|
|
|
|
POSTING_READ(PIPECONF(pipe));
|
|
|
|
}
|
|
|
|
|
2013-01-19 01:11:38 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-03-27 07:44:56 +08:00
|
|
|
static void intel_set_pipe_csc(struct drm_crtc *crtc)
|
2013-01-19 01:11:38 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
uint16_t coeff = 0x7800; /* 1.0 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO: Check what kind of values actually come out of the pipe
|
|
|
|
* with these coeff/postoff values and adjust to get the best
|
|
|
|
* accuracy. Perhaps we even need to take the bpc value into
|
|
|
|
* consideration.
|
|
|
|
*/
|
|
|
|
|
2013-03-27 07:44:56 +08:00
|
|
|
if (intel_crtc->config.limited_color_range)
|
2013-01-19 01:11:38 +08:00
|
|
|
coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GY/GU and RY/RU should be the other way around according
|
|
|
|
* to BSpec, but reality doesn't agree. Just set them up in
|
|
|
|
* a way that results in the correct picture.
|
|
|
|
*/
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
|
|
|
|
I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
|
|
|
|
I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
|
|
|
|
I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen > 6) {
|
|
|
|
uint16_t postoff = 0;
|
|
|
|
|
2013-03-27 07:44:56 +08:00
|
|
|
if (intel_crtc->config.limited_color_range)
|
2013-01-19 01:11:38 +08:00
|
|
|
postoff = (16 * (1 << 13) / 255) & 0x1fff;
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
|
|
|
|
I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
|
|
|
|
I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_MODE(pipe), 0);
|
|
|
|
} else {
|
|
|
|
uint32_t mode = CSC_MODE_YUV_TO_RGB;
|
|
|
|
|
2013-03-27 07:44:56 +08:00
|
|
|
if (intel_crtc->config.limited_color_range)
|
2013-01-19 01:11:38 +08:00
|
|
|
mode |= CSC_BLACK_SCREEN_OFFSET;
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_MODE(pipe), mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-19 17:24:36 +08:00
|
|
|
static void haswell_set_pipeconf(struct drm_crtc *crtc)
|
2012-10-05 23:05:57 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-04-18 02:15:07 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
2012-10-05 23:05:57 +08:00
|
|
|
uint32_t val;
|
|
|
|
|
2012-10-24 04:29:59 +08:00
|
|
|
val = I915_READ(PIPECONF(cpu_transcoder));
|
2012-10-05 23:05:57 +08:00
|
|
|
|
|
|
|
val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
|
2013-04-25 23:54:44 +08:00
|
|
|
if (intel_crtc->config.dither)
|
2012-10-05 23:05:57 +08:00
|
|
|
val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
|
|
|
|
|
|
|
|
val &= ~PIPECONF_INTERLACE_MASK_HSW;
|
2013-04-19 17:24:36 +08:00
|
|
|
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
2012-10-05 23:05:57 +08:00
|
|
|
val |= PIPECONF_INTERLACED_ILK;
|
|
|
|
else
|
|
|
|
val |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
2012-10-24 04:29:59 +08:00
|
|
|
I915_WRITE(PIPECONF(cpu_transcoder), val);
|
|
|
|
POSTING_READ(PIPECONF(cpu_transcoder));
|
2012-10-05 23:05:57 +08:00
|
|
|
}
|
|
|
|
|
2012-09-12 21:06:34 +08:00
|
|
|
static bool ironlake_compute_clocks(struct drm_crtc *crtc,
|
|
|
|
struct drm_display_mode *adjusted_mode,
|
|
|
|
intel_clock_t *clock,
|
|
|
|
bool *has_reduced_clock,
|
|
|
|
intel_clock_t *reduced_clock)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
|
int refclk;
|
2009-03-18 20:13:27 +08:00
|
|
|
const intel_limit_t *limit;
|
2013-04-30 20:01:44 +08:00
|
|
|
bool ret, is_lvds = false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-09-12 21:06:34 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
|
|
|
|
switch (intel_encoder->type) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
is_lvds = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-03 04:03:05 +08:00
|
|
|
refclk = ironlake_get_refclk(crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2010-12-15 04:04:54 +08:00
|
|
|
limit = intel_limit(crtc, refclk);
|
2012-09-12 21:06:34 +08:00
|
|
|
ret = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
|
|
|
|
clock);
|
|
|
|
if (!ret)
|
|
|
|
return false;
|
2010-07-09 15:45:04 +08:00
|
|
|
|
2010-01-06 22:05:56 +08:00
|
|
|
if (is_lvds && dev_priv->lvds_downclock_avail) {
|
2012-01-11 07:09:36 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* by using the FP0/FP1. In such case we will disable the LVDS
|
|
|
|
* downclock feature.
|
|
|
|
*/
|
2012-09-12 21:06:34 +08:00
|
|
|
*has_reduced_clock = limit->find_pll(limit, crtc,
|
|
|
|
dev_priv->lvds_downclock,
|
|
|
|
refclk,
|
|
|
|
clock,
|
|
|
|
reduced_clock);
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
2012-05-30 20:52:26 +08:00
|
|
|
|
2012-09-12 21:06:34 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-10-27 21:58:40 +08:00
|
|
|
static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t temp;
|
|
|
|
|
|
|
|
temp = I915_READ(SOUTH_CHICKEN1);
|
|
|
|
if (temp & FDI_BC_BIFURCATION_SELECT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
|
|
|
|
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
temp |= FDI_BC_BIFURCATION_SELECT;
|
|
|
|
DRM_DEBUG_KMS("enabling fdi C rx\n");
|
|
|
|
I915_WRITE(SOUTH_CHICKEN1, temp);
|
|
|
|
POSTING_READ(SOUTH_CHICKEN1);
|
|
|
|
}
|
|
|
|
|
2013-04-19 17:24:44 +08:00
|
|
|
static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
switch (intel_crtc->pipe) {
|
|
|
|
case PIPE_A:
|
|
|
|
break;
|
|
|
|
case PIPE_B:
|
|
|
|
if (intel_crtc->config.fdi_lanes > 2)
|
|
|
|
WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
|
|
|
|
else
|
|
|
|
cpt_enable_fdi_bc_bifurcation(dev);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case PIPE_C:
|
2012-10-27 21:58:40 +08:00
|
|
|
cpt_enable_fdi_bc_bifurcation(dev);
|
|
|
|
|
2013-04-19 17:24:44 +08:00
|
|
|
break;
|
2012-10-27 21:58:40 +08:00
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-29 21:29:32 +08:00
|
|
|
int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Account for spread spectrum to avoid
|
|
|
|
* oversubscribing the link. Max center spread
|
|
|
|
* is 2.5%; use 5% for safety's sake.
|
|
|
|
*/
|
|
|
|
u32 bps = target_clock * bpp * 21 / 20;
|
|
|
|
return bps / (link_bw * 8) + 1;
|
|
|
|
}
|
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
|
|
|
|
{
|
|
|
|
return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
|
|
|
|
}
|
|
|
|
|
2012-09-21 05:36:05 +08:00
|
|
|
static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
2013-04-20 23:19:46 +08:00
|
|
|
u32 *fp,
|
2013-04-05 04:20:34 +08:00
|
|
|
intel_clock_t *reduced_clock, u32 *fp2)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-09-21 05:36:05 +08:00
|
|
|
struct drm_crtc *crtc = &intel_crtc->base;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-09-21 05:36:05 +08:00
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
|
uint32_t dpll;
|
2013-03-27 07:44:53 +08:00
|
|
|
int factor, num_connectors = 0;
|
2013-04-30 20:01:45 +08:00
|
|
|
bool is_lvds = false, is_sdvo = false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-09-21 05:36:05 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
|
|
|
|
switch (intel_encoder->type) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
is_lvds = true;
|
|
|
|
break;
|
|
|
|
case INTEL_OUTPUT_SDVO:
|
2009-01-03 05:33:00 +08:00
|
|
|
case INTEL_OUTPUT_HDMI:
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
is_sdvo = true;
|
|
|
|
break;
|
|
|
|
}
|
2009-02-14 09:56:52 +08:00
|
|
|
|
2010-03-26 02:48:48 +08:00
|
|
|
num_connectors++;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-12-04 05:35:48 +08:00
|
|
|
/* Enable autotuning of the PLL clock (if permissible) */
|
2011-03-31 04:01:07 +08:00
|
|
|
factor = 21;
|
|
|
|
if (is_lvds) {
|
|
|
|
if ((intel_panel_use_ssc(dev_priv) &&
|
2013-05-10 07:03:18 +08:00
|
|
|
dev_priv->vbt.lvds_ssc_freq == 100) ||
|
2013-04-05 04:20:33 +08:00
|
|
|
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
|
2011-03-31 04:01:07 +08:00
|
|
|
factor = 25;
|
2013-04-30 20:01:45 +08:00
|
|
|
} else if (intel_crtc->config.sdvo_tv_clock)
|
2011-03-31 04:01:07 +08:00
|
|
|
factor = 20;
|
2010-12-04 05:35:48 +08:00
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
if (ironlake_needs_fb_cb_tune(&intel_crtc->config.dpll, factor))
|
2013-04-05 04:20:32 +08:00
|
|
|
*fp |= FP_CB_TUNE;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-04-05 04:20:34 +08:00
|
|
|
if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
|
|
|
|
*fp2 |= FP_CB_TUNE;
|
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
dpll = 0;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2011-03-31 04:01:08 +08:00
|
|
|
if (is_lvds)
|
|
|
|
dpll |= DPLLB_MODE_LVDS;
|
|
|
|
else
|
|
|
|
dpll |= DPLLB_MODE_DAC_SERIAL;
|
2013-04-19 17:14:37 +08:00
|
|
|
|
|
|
|
if (intel_crtc->config.pixel_multiplier > 1) {
|
|
|
|
dpll |= (intel_crtc->config.pixel_multiplier - 1)
|
|
|
|
<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
|
2011-03-31 04:01:08 +08:00
|
|
|
}
|
2013-04-19 17:14:37 +08:00
|
|
|
|
|
|
|
if (is_sdvo)
|
|
|
|
dpll |= DPLL_DVO_HIGH_SPEED;
|
2013-04-19 17:14:36 +08:00
|
|
|
if (intel_crtc->config.has_dp_encoder)
|
2011-03-31 04:01:08 +08:00
|
|
|
dpll |= DPLL_DVO_HIGH_SPEED;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-03-31 04:01:08 +08:00
|
|
|
/* compute bitmask from p1 value */
|
2013-04-20 23:19:46 +08:00
|
|
|
dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
2011-03-31 04:01:08 +08:00
|
|
|
/* also FPA1 */
|
2013-04-20 23:19:46 +08:00
|
|
|
dpll |= (1 << (intel_crtc->config.dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
2011-03-31 04:01:08 +08:00
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
switch (intel_crtc->config.dpll.p2) {
|
2011-03-31 04:01:08 +08:00
|
|
|
case 5:
|
|
|
|
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
|
|
|
break;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2013-04-30 20:01:42 +08:00
|
|
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
|
2009-02-14 09:56:52 +08:00
|
|
|
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
else
|
|
|
|
dpll |= PLL_REF_INPUT_DREFCLK;
|
|
|
|
|
2012-09-21 05:36:05 +08:00
|
|
|
return dpll;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
int x, int y,
|
|
|
|
struct drm_framebuffer *fb)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *adjusted_mode =
|
|
|
|
&intel_crtc->config.adjusted_mode;
|
|
|
|
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
|
2012-09-21 05:36:05 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
|
|
|
int num_connectors = 0;
|
|
|
|
intel_clock_t clock, reduced_clock;
|
2013-04-19 17:14:31 +08:00
|
|
|
u32 dpll = 0, fp = 0, fp2 = 0;
|
2012-09-21 05:36:06 +08:00
|
|
|
bool ok, has_reduced_clock = false;
|
2013-03-28 17:41:59 +08:00
|
|
|
bool is_lvds = false;
|
2012-09-21 05:36:05 +08:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
switch (encoder->type) {
|
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
is_lvds = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_connectors++;
|
2011-03-31 04:01:08 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-10-05 23:05:56 +08:00
|
|
|
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
|
|
|
|
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
|
2011-03-31 04:01:08 +08:00
|
|
|
|
2012-09-21 05:36:05 +08:00
|
|
|
ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
|
|
|
|
&has_reduced_clock, &reduced_clock);
|
|
|
|
if (!ok) {
|
|
|
|
DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
|
|
|
return -EINVAL;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2013-03-28 17:42:02 +08:00
|
|
|
/* Compat-code for transition, will disappear. */
|
|
|
|
if (!intel_crtc->config.clock_set) {
|
|
|
|
intel_crtc->config.dpll.n = clock.n;
|
|
|
|
intel_crtc->config.dpll.m1 = clock.m1;
|
|
|
|
intel_crtc->config.dpll.m2 = clock.m2;
|
|
|
|
intel_crtc->config.dpll.p1 = clock.p1;
|
|
|
|
intel_crtc->config.dpll.p2 = clock.p2;
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-09-21 05:36:05 +08:00
|
|
|
/* Ensure that the cursor is valid for the new mode before changing... */
|
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
|
|
2012-10-05 23:05:56 +08:00
|
|
|
/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
|
2013-03-28 17:41:59 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
2012-04-21 00:11:53 +08:00
|
|
|
struct intel_pch_pll *pll;
|
2011-10-13 00:51:31 +08:00
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll);
|
2013-04-19 17:14:31 +08:00
|
|
|
if (has_reduced_clock)
|
2013-04-20 23:19:46 +08:00
|
|
|
fp2 = i9xx_dpll_compute_fp(&reduced_clock);
|
2013-04-19 17:14:31 +08:00
|
|
|
|
2013-04-20 23:19:46 +08:00
|
|
|
dpll = ironlake_compute_dpll(intel_crtc,
|
2013-04-19 17:14:31 +08:00
|
|
|
&fp, &reduced_clock,
|
|
|
|
has_reduced_clock ? &fp2 : NULL);
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
pll = intel_get_pch_pll(intel_crtc, dpll, fp);
|
|
|
|
if (pll == NULL) {
|
2013-04-17 22:48:49 +08:00
|
|
|
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
|
|
|
|
pipe_name(pipe));
|
2011-10-13 00:51:31 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
2012-04-21 00:11:53 +08:00
|
|
|
} else
|
|
|
|
intel_put_pch_pll(intel_crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2013-04-03 05:42:31 +08:00
|
|
|
if (intel_crtc->config.has_dp_encoder)
|
|
|
|
intel_dp_set_m_n(intel_crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-11-27 00:22:07 +08:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
encoder->pre_pll_enable(encoder);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
if (intel_crtc->pch_pll) {
|
|
|
|
I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
|
2010-09-11 20:48:45 +08:00
|
|
|
|
2009-07-24 01:00:32 +08:00
|
|
|
/* Wait for the clocks to stabilize. */
|
2012-04-21 00:11:53 +08:00
|
|
|
POSTING_READ(intel_crtc->pch_pll->pll_reg);
|
2009-07-24 01:00:32 +08:00
|
|
|
udelay(150);
|
|
|
|
|
2011-03-31 04:01:07 +08:00
|
|
|
/* The pixel multiplier can only be updated once the
|
|
|
|
* DPLL is enabled and the clocks are stable.
|
|
|
|
*
|
|
|
|
* So write it again.
|
|
|
|
*/
|
2012-04-21 00:11:53 +08:00
|
|
|
I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-09-11 20:48:45 +08:00
|
|
|
intel_crtc->lowfreq_avail = false;
|
2012-04-21 00:11:53 +08:00
|
|
|
if (intel_crtc->pch_pll) {
|
2011-10-13 00:51:31 +08:00
|
|
|
if (is_lvds && has_reduced_clock && i915_powersave) {
|
2012-04-21 00:11:53 +08:00
|
|
|
I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
|
2011-10-13 00:51:31 +08:00
|
|
|
intel_crtc->lowfreq_avail = true;
|
|
|
|
} else {
|
2012-04-21 00:11:53 +08:00
|
|
|
I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-02 05:10:53 +08:00
|
|
|
intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
|
2010-09-11 20:48:45 +08:00
|
|
|
|
2013-02-14 23:54:22 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
|
|
|
intel_cpu_transcoder_set_m_n(intel_crtc,
|
|
|
|
&intel_crtc->config.fdi_m_n);
|
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-04-19 17:24:44 +08:00
|
|
|
if (IS_IVYBRIDGE(dev))
|
|
|
|
ivybridge_update_fdi_bc_bifurcation(intel_crtc);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-04-19 17:24:36 +08:00
|
|
|
ironlake_set_pipeconf(crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-09-12 21:06:32 +08:00
|
|
|
/* Set up the display plane register */
|
|
|
|
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
|
2011-01-05 07:09:30 +08:00
|
|
|
POSTING_READ(DSPCNTR(plane));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
ret = intel_pipe_set_base(crtc, x, y, fb);
|
2009-06-26 11:23:55 +08:00
|
|
|
|
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
2013-04-30 01:34:16 +08:00
|
|
|
return ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2013-04-04 19:28:53 +08:00
|
|
|
static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
enum transcoder transcoder = pipe_config->cpu_transcoder;
|
|
|
|
|
|
|
|
pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder));
|
|
|
|
pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder));
|
|
|
|
pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
|
|
|
|
& ~TU_SIZE_MASK;
|
|
|
|
pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
|
|
|
|
pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder))
|
|
|
|
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
|
|
|
|
}
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
static void ironlake_get_pfit_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
tmp = I915_READ(PF_CTL(crtc->pipe));
|
|
|
|
|
|
|
|
if (tmp & PF_ENABLE) {
|
|
|
|
pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe));
|
|
|
|
pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
2013-05-22 06:50:22 +08:00
|
|
|
pipe_config->cpu_transcoder = crtc->pipe;
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
tmp = I915_READ(PIPECONF(crtc->pipe));
|
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
return false;
|
|
|
|
|
2013-05-03 17:49:46 +08:00
|
|
|
if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
|
2013-03-28 17:42:01 +08:00
|
|
|
pipe_config->has_pch_encoder = true;
|
|
|
|
|
2013-04-30 01:33:42 +08:00
|
|
|
tmp = I915_READ(FDI_RX_CTL(crtc->pipe));
|
|
|
|
pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
|
|
|
|
FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
2013-04-04 19:28:53 +08:00
|
|
|
|
|
|
|
ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
2013-04-30 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
ironlake_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-30 02:35:20 +08:00
|
|
|
static void haswell_modeset_global_resources(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
bool enable = false;
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
|
2013-05-31 23:49:17 +08:00
|
|
|
if (!crtc->base.enabled)
|
|
|
|
continue;
|
2013-01-30 02:35:20 +08:00
|
|
|
|
2013-05-31 23:49:17 +08:00
|
|
|
if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size ||
|
|
|
|
crtc->config.cpu_transcoder != TRANSCODER_EDP)
|
2013-01-30 02:35:20 +08:00
|
|
|
enable = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_set_power_well(dev, enable);
|
|
|
|
}
|
|
|
|
|
2012-10-05 23:05:55 +08:00
|
|
|
static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
int x, int y,
|
|
|
|
struct drm_framebuffer *fb)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *adjusted_mode =
|
|
|
|
&intel_crtc->config.adjusted_mode;
|
|
|
|
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
|
2012-10-05 23:05:55 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int plane = intel_crtc->plane;
|
|
|
|
int num_connectors = 0;
|
2013-03-28 17:41:59 +08:00
|
|
|
bool is_cpu_edp = false;
|
2012-10-05 23:05:55 +08:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
switch (encoder->type) {
|
|
|
|
case INTEL_OUTPUT_EDP:
|
2013-05-08 18:14:03 +08:00
|
|
|
if (enc_to_dig_port(&encoder->base)->port == PORT_A)
|
2012-10-05 23:05:55 +08:00
|
|
|
is_cpu_edp = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_connectors++;
|
|
|
|
}
|
|
|
|
|
2012-10-05 23:05:56 +08:00
|
|
|
WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
|
|
|
|
num_connectors, pipe_name(pipe));
|
|
|
|
|
2012-10-05 23:05:58 +08:00
|
|
|
if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-10-05 23:05:55 +08:00
|
|
|
/* Ensure that the cursor is valid for the new mode before changing... */
|
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
|
|
2013-04-03 05:42:31 +08:00
|
|
|
if (intel_crtc->config.has_dp_encoder)
|
|
|
|
intel_dp_set_m_n(intel_crtc);
|
2012-10-05 23:05:55 +08:00
|
|
|
|
|
|
|
intel_crtc->lowfreq_avail = false;
|
|
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
|
|
|
|
|
2013-02-14 23:54:22 +08:00
|
|
|
if (intel_crtc->config.has_pch_encoder) {
|
|
|
|
intel_cpu_transcoder_set_m_n(intel_crtc,
|
|
|
|
&intel_crtc->config.fdi_m_n);
|
|
|
|
}
|
2012-10-05 23:05:55 +08:00
|
|
|
|
2013-04-19 17:24:36 +08:00
|
|
|
haswell_set_pipeconf(crtc);
|
2012-10-05 23:05:55 +08:00
|
|
|
|
2013-03-27 07:44:56 +08:00
|
|
|
intel_set_pipe_csc(crtc);
|
2013-01-19 01:11:38 +08:00
|
|
|
|
2012-10-05 23:05:55 +08:00
|
|
|
/* Set up the display plane register */
|
2013-01-19 01:11:38 +08:00
|
|
|
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
|
2012-10-05 23:05:55 +08:00
|
|
|
POSTING_READ(DSPCNTR(plane));
|
|
|
|
|
|
|
|
ret = intel_pipe_set_base(crtc, x, y, fb);
|
|
|
|
|
|
|
|
intel_update_watermarks(dev);
|
|
|
|
|
2009-06-06 16:45:59 +08:00
|
|
|
return ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-05-08 05:34:16 +08:00
|
|
|
enum intel_display_power_domain pfit_domain;
|
2013-03-28 17:42:00 +08:00
|
|
|
uint32_t tmp;
|
|
|
|
|
2013-05-22 06:50:22 +08:00
|
|
|
pipe_config->cpu_transcoder = crtc->pipe;
|
|
|
|
tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
|
|
|
|
if (tmp & TRANS_DDI_FUNC_ENABLE) {
|
|
|
|
enum pipe trans_edp_pipe;
|
|
|
|
switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
|
|
|
|
default:
|
|
|
|
WARN(1, "unknown pipe linked to edp transcoder\n");
|
|
|
|
case TRANS_DDI_EDP_INPUT_A_ONOFF:
|
|
|
|
case TRANS_DDI_EDP_INPUT_A_ON:
|
|
|
|
trans_edp_pipe = PIPE_A;
|
|
|
|
break;
|
|
|
|
case TRANS_DDI_EDP_INPUT_B_ONOFF:
|
|
|
|
trans_edp_pipe = PIPE_B;
|
|
|
|
break;
|
|
|
|
case TRANS_DDI_EDP_INPUT_C_ONOFF:
|
|
|
|
trans_edp_pipe = PIPE_C;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trans_edp_pipe == crtc->pipe)
|
|
|
|
pipe_config->cpu_transcoder = TRANSCODER_EDP;
|
|
|
|
}
|
|
|
|
|
2013-05-03 23:15:36 +08:00
|
|
|
if (!intel_display_power_enabled(dev,
|
2013-05-22 06:50:22 +08:00
|
|
|
POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
|
2013-04-19 03:35:40 +08:00
|
|
|
return false;
|
|
|
|
|
2013-05-22 06:50:22 +08:00
|
|
|
tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
|
2013-03-28 17:42:00 +08:00
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
return false;
|
|
|
|
|
2013-03-28 17:42:01 +08:00
|
|
|
/*
|
2013-04-19 03:35:41 +08:00
|
|
|
* Haswell has only FDI/PCH transcoder A. It is which is connected to
|
2013-03-28 17:42:01 +08:00
|
|
|
* DDI E. So just check whether this pipe is wired to DDI E and whether
|
|
|
|
* the PCH transcoder is on.
|
|
|
|
*/
|
2013-05-22 06:50:22 +08:00
|
|
|
tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
|
2013-03-28 17:42:01 +08:00
|
|
|
if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
|
2013-05-03 17:49:46 +08:00
|
|
|
I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
|
2013-03-28 17:42:01 +08:00
|
|
|
pipe_config->has_pch_encoder = true;
|
|
|
|
|
2013-04-30 01:33:42 +08:00
|
|
|
tmp = I915_READ(FDI_RX_CTL(PIPE_A));
|
|
|
|
pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
|
|
|
|
FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
2013-04-04 19:28:53 +08:00
|
|
|
|
|
|
|
ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
2013-04-30 01:33:42 +08:00
|
|
|
}
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
|
|
|
|
if (intel_display_power_enabled(dev, pfit_domain))
|
|
|
|
ironlake_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
|
|
|
|
(I915_READ(IPS_CTL) & IPS_ENABLE);
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-03-31 04:01:02 +08:00
|
|
|
static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
int x, int y,
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
struct drm_framebuffer *fb)
|
2011-03-31 04:01:02 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-11-01 02:26:13 +08:00
|
|
|
struct drm_encoder_helper_funcs *encoder_funcs;
|
|
|
|
struct intel_encoder *encoder;
|
2011-03-31 04:01:03 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *adjusted_mode =
|
|
|
|
&intel_crtc->config.adjusted_mode;
|
|
|
|
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
|
2011-03-31 04:01:03 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
2011-03-31 04:01:02 +08:00
|
|
|
int ret;
|
|
|
|
|
2011-03-31 04:01:03 +08:00
|
|
|
drm_vblank_pre_modeset(dev, pipe);
|
2009-06-26 11:23:55 +08:00
|
|
|
|
2013-03-27 07:44:50 +08:00
|
|
|
ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb);
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
drm_vblank_post_modeset(dev, pipe);
|
2009-02-11 21:25:09 +08:00
|
|
|
|
2012-11-01 02:26:13 +08:00
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
|
|
|
|
encoder->base.base.id,
|
|
|
|
drm_get_encoder_name(&encoder->base),
|
|
|
|
mode->base.id, mode->name);
|
2013-03-27 07:44:53 +08:00
|
|
|
if (encoder->mode_set) {
|
|
|
|
encoder->mode_set(encoder);
|
|
|
|
} else {
|
|
|
|
encoder_funcs = encoder->base.helper_private;
|
|
|
|
encoder_funcs->mode_set(&encoder->base, mode, adjusted_mode);
|
|
|
|
}
|
2012-11-01 02:26:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 20:42:19 +08:00
|
|
|
static bool intel_eld_uptodate(struct drm_connector *connector,
|
|
|
|
int reg_eldv, uint32_t bits_eldv,
|
|
|
|
int reg_elda, uint32_t bits_elda,
|
|
|
|
int reg_edid)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
|
|
uint8_t *eld = connector->eld;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
i = I915_READ(reg_eldv);
|
|
|
|
i &= bits_eldv;
|
|
|
|
|
|
|
|
if (!eld[0])
|
|
|
|
return !i;
|
|
|
|
|
|
|
|
if (!i)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
i = I915_READ(reg_elda);
|
|
|
|
i &= ~bits_elda;
|
|
|
|
I915_WRITE(reg_elda, i);
|
|
|
|
|
|
|
|
for (i = 0; i < eld[2]; i++)
|
|
|
|
if (I915_READ(reg_edid) != *((uint32_t *)eld + i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
static void g4x_write_eld(struct drm_connector *connector,
|
|
|
|
struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
|
|
uint8_t *eld = connector->eld;
|
|
|
|
uint32_t eldv;
|
|
|
|
uint32_t len;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
i = I915_READ(G4X_AUD_VID_DID);
|
|
|
|
|
|
|
|
if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
|
|
|
|
eldv = G4X_ELDV_DEVCL_DEVBLC;
|
|
|
|
else
|
|
|
|
eldv = G4X_ELDV_DEVCTG;
|
|
|
|
|
2011-12-09 20:42:19 +08:00
|
|
|
if (intel_eld_uptodate(connector,
|
|
|
|
G4X_AUD_CNTL_ST, eldv,
|
|
|
|
G4X_AUD_CNTL_ST, G4X_ELD_ADDR,
|
|
|
|
G4X_HDMIW_HDMIEDID))
|
|
|
|
return;
|
|
|
|
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
i = I915_READ(G4X_AUD_CNTL_ST);
|
|
|
|
i &= ~(eldv | G4X_ELD_ADDR);
|
|
|
|
len = (i >> 9) & 0x1f; /* ELD buffer size */
|
|
|
|
I915_WRITE(G4X_AUD_CNTL_ST, i);
|
|
|
|
|
|
|
|
if (!eld[0])
|
|
|
|
return;
|
|
|
|
|
|
|
|
len = min_t(uint8_t, eld[2], len);
|
|
|
|
DRM_DEBUG_DRIVER("ELD size %d\n", len);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
|
|
|
|
|
|
|
|
i = I915_READ(G4X_AUD_CNTL_ST);
|
|
|
|
i |= eldv;
|
|
|
|
I915_WRITE(G4X_AUD_CNTL_ST, i);
|
|
|
|
}
|
|
|
|
|
2012-08-16 22:43:37 +08:00
|
|
|
static void haswell_write_eld(struct drm_connector *connector,
|
|
|
|
struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
|
|
uint8_t *eld = connector->eld;
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2013-01-22 23:25:25 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-08-16 22:43:37 +08:00
|
|
|
uint32_t eldv;
|
|
|
|
uint32_t i;
|
|
|
|
int len;
|
|
|
|
int pipe = to_intel_crtc(crtc)->pipe;
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe);
|
|
|
|
int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe);
|
|
|
|
int aud_config = HSW_AUD_CFG(pipe);
|
|
|
|
int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD;
|
|
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
|
|
|
|
|
|
|
|
/* Audio output enable */
|
|
|
|
DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
|
|
|
|
tmp = I915_READ(aud_cntrl_st2);
|
|
|
|
tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4));
|
|
|
|
I915_WRITE(aud_cntrl_st2, tmp);
|
|
|
|
|
|
|
|
/* Wait for 1 vertical blank */
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
|
|
|
/* Set ELD valid state */
|
|
|
|
tmp = I915_READ(aud_cntrl_st2);
|
|
|
|
DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
|
|
|
|
tmp |= (AUDIO_ELD_VALID_A << (pipe * 4));
|
|
|
|
I915_WRITE(aud_cntrl_st2, tmp);
|
|
|
|
tmp = I915_READ(aud_cntrl_st2);
|
|
|
|
DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
|
|
|
|
|
|
|
|
/* Enable HDMI mode */
|
|
|
|
tmp = I915_READ(aud_config);
|
|
|
|
DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
|
|
|
|
/* clear N_programing_enable and N_value_index */
|
|
|
|
tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
|
|
|
|
I915_WRITE(aud_config, tmp);
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
|
|
|
|
|
|
|
|
eldv = AUDIO_ELD_VALID_A << (pipe * 4);
|
2013-01-22 23:25:25 +08:00
|
|
|
intel_crtc->eld_vld = true;
|
2012-08-16 22:43:37 +08:00
|
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
|
|
|
|
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
|
|
|
|
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
|
|
|
|
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
|
|
|
|
} else
|
|
|
|
I915_WRITE(aud_config, 0);
|
|
|
|
|
|
|
|
if (intel_eld_uptodate(connector,
|
|
|
|
aud_cntrl_st2, eldv,
|
|
|
|
aud_cntl_st, IBX_ELD_ADDRESS,
|
|
|
|
hdmiw_hdmiedid))
|
|
|
|
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);
|
|
|
|
i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */
|
|
|
|
DRM_DEBUG_DRIVER("port num:%d\n", i);
|
|
|
|
|
|
|
|
len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */
|
|
|
|
DRM_DEBUG_DRIVER("ELD size %d\n", len);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
|
|
|
|
|
|
|
|
i = I915_READ(aud_cntrl_st2);
|
|
|
|
i |= eldv;
|
|
|
|
I915_WRITE(aud_cntrl_st2, i);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
static void ironlake_write_eld(struct drm_connector *connector,
|
|
|
|
struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
|
|
uint8_t *eld = connector->eld;
|
|
|
|
uint32_t eldv;
|
|
|
|
uint32_t i;
|
|
|
|
int len;
|
|
|
|
int hdmiw_hdmiedid;
|
2012-01-07 04:41:31 +08:00
|
|
|
int aud_config;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
int aud_cntl_st;
|
|
|
|
int aud_cntrl_st2;
|
2012-08-09 16:52:18 +08:00
|
|
|
int pipe = to_intel_crtc(crtc)->pipe;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
|
2011-12-09 20:42:17 +08:00
|
|
|
if (HAS_PCH_IBX(connector->dev)) {
|
2012-08-09 16:52:18 +08:00
|
|
|
hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
|
|
|
|
aud_config = IBX_AUD_CFG(pipe);
|
|
|
|
aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
|
2011-12-09 20:42:18 +08:00
|
|
|
aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
} else {
|
2012-08-09 16:52:18 +08:00
|
|
|
hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
|
|
|
|
aud_config = CPT_AUD_CFG(pipe);
|
|
|
|
aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
|
2011-12-09 20:42:18 +08:00
|
|
|
aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
}
|
|
|
|
|
2012-08-09 16:52:18 +08:00
|
|
|
DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
|
|
|
|
i = I915_READ(aud_cntl_st);
|
2012-08-09 16:52:18 +08:00
|
|
|
i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
if (!i) {
|
|
|
|
DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
|
|
|
|
/* operate blindly on all ports */
|
2011-12-09 20:42:18 +08:00
|
|
|
eldv = IBX_ELD_VALIDB;
|
|
|
|
eldv |= IBX_ELD_VALIDB << 4;
|
|
|
|
eldv |= IBX_ELD_VALIDB << 8;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
} else {
|
2013-04-17 22:48:47 +08:00
|
|
|
DRM_DEBUG_DRIVER("ELD on port %c\n", port_name(i));
|
2011-12-09 20:42:18 +08:00
|
|
|
eldv = IBX_ELD_VALIDB << ((i - 1) * 4);
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 20:42:19 +08:00
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
|
|
|
|
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
|
|
|
|
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
|
2012-01-07 04:41:31 +08:00
|
|
|
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
|
|
|
|
} else
|
|
|
|
I915_WRITE(aud_config, 0);
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
|
2011-12-09 20:42:19 +08:00
|
|
|
if (intel_eld_uptodate(connector,
|
|
|
|
aud_cntrl_st2, eldv,
|
|
|
|
aud_cntl_st, IBX_ELD_ADDRESS,
|
|
|
|
hdmiw_hdmiedid))
|
|
|
|
return;
|
|
|
|
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
i = I915_READ(aud_cntrl_st2);
|
|
|
|
i &= ~eldv;
|
|
|
|
I915_WRITE(aud_cntrl_st2, i);
|
|
|
|
|
|
|
|
if (!eld[0])
|
|
|
|
return;
|
|
|
|
|
|
|
|
i = I915_READ(aud_cntl_st);
|
2011-12-09 20:42:18 +08:00
|
|
|
i &= ~IBX_ELD_ADDRESS;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
I915_WRITE(aud_cntl_st, i);
|
|
|
|
|
|
|
|
len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */
|
|
|
|
DRM_DEBUG_DRIVER("ELD size %d\n", len);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
|
|
|
|
|
|
|
|
i = I915_READ(aud_cntrl_st2);
|
|
|
|
i |= eldv;
|
|
|
|
I915_WRITE(aud_cntrl_st2, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void intel_write_eld(struct drm_encoder *encoder,
|
|
|
|
struct drm_display_mode *mode)
|
|
|
|
{
|
|
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
|
|
struct drm_connector *connector;
|
|
|
|
struct drm_device *dev = encoder->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
connector = drm_select_eld(encoder, mode);
|
|
|
|
if (!connector)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
|
|
|
connector->base.id,
|
|
|
|
drm_get_connector_name(connector),
|
|
|
|
connector->encoder->base.id,
|
|
|
|
drm_get_encoder_name(connector->encoder));
|
|
|
|
|
|
|
|
connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
|
|
|
|
|
|
|
|
if (dev_priv->display.write_eld)
|
|
|
|
dev_priv->display.write_eld(connector, crtc);
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/** Loads the palette/gamma unit for the CRTC with the prepared values */
|
|
|
|
void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-06-01 03:33:22 +08:00
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
|
int palreg = PALETTE(pipe);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int i;
|
2013-06-01 03:33:22 +08:00
|
|
|
bool reenable_ips = false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
/* The clocks have to be on to load the palette. */
|
2012-02-25 01:12:45 +08:00
|
|
|
if (!crtc->enabled || !intel_crtc->active)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
return;
|
|
|
|
|
2009-12-04 06:14:42 +08:00
|
|
|
/* use legacy palette for Ironlake */
|
2009-10-23 07:11:14 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev))
|
2013-06-01 03:33:22 +08:00
|
|
|
palreg = LGC_PALETTE(pipe);
|
|
|
|
|
|
|
|
/* Workaround : Do not read or write the pipe palette/gamma data while
|
|
|
|
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
|
|
|
|
*/
|
|
|
|
if (intel_crtc->config.ips_enabled &&
|
|
|
|
((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
|
|
|
|
GAMMA_MODE_MODE_SPLIT)) {
|
|
|
|
hsw_disable_ips(intel_crtc);
|
|
|
|
reenable_ips = true;
|
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
I915_WRITE(palreg + 4 * i,
|
|
|
|
(intel_crtc->lut_r[i] << 16) |
|
|
|
|
(intel_crtc->lut_g[i] << 8) |
|
|
|
|
intel_crtc->lut_b[i]);
|
|
|
|
}
|
2013-06-01 03:33:22 +08:00
|
|
|
|
|
|
|
if (reenable_ips)
|
|
|
|
hsw_enable_ips(intel_crtc);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-08-07 18:01:38 +08:00
|
|
|
static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
bool visible = base != 0;
|
|
|
|
u32 cntl;
|
|
|
|
|
|
|
|
if (intel_crtc->cursor_visible == visible)
|
|
|
|
return;
|
|
|
|
|
2011-02-08 04:26:52 +08:00
|
|
|
cntl = I915_READ(_CURACNTR);
|
2010-08-07 18:01:38 +08:00
|
|
|
if (visible) {
|
|
|
|
/* On these chipsets we can only modify the base whilst
|
|
|
|
* the cursor is disabled.
|
|
|
|
*/
|
2011-02-08 04:26:52 +08:00
|
|
|
I915_WRITE(_CURABASE, base);
|
2010-08-07 18:01:38 +08:00
|
|
|
|
|
|
|
cntl &= ~(CURSOR_FORMAT_MASK);
|
|
|
|
/* XXX width must be 64, stride 256 => 0x00 << 28 */
|
|
|
|
cntl |= CURSOR_ENABLE |
|
|
|
|
CURSOR_GAMMA_ENABLE |
|
|
|
|
CURSOR_FORMAT_ARGB;
|
|
|
|
} else
|
|
|
|
cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
|
2011-02-08 04:26:52 +08:00
|
|
|
I915_WRITE(_CURACNTR, cntl);
|
2010-08-07 18:01:38 +08:00
|
|
|
|
|
|
|
intel_crtc->cursor_visible = visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
bool visible = base != 0;
|
|
|
|
|
|
|
|
if (intel_crtc->cursor_visible != visible) {
|
2011-02-18 02:40:53 +08:00
|
|
|
uint32_t cntl = I915_READ(CURCNTR(pipe));
|
2010-08-07 18:01:38 +08:00
|
|
|
if (base) {
|
|
|
|
cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
|
|
|
|
cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
|
|
|
cntl |= pipe << 28; /* Connect to correct pipe */
|
|
|
|
} else {
|
|
|
|
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
|
|
|
|
cntl |= CURSOR_MODE_DISABLE;
|
|
|
|
}
|
2011-02-08 04:26:52 +08:00
|
|
|
I915_WRITE(CURCNTR(pipe), cntl);
|
2010-08-07 18:01:38 +08:00
|
|
|
|
|
|
|
intel_crtc->cursor_visible = visible;
|
|
|
|
}
|
|
|
|
/* and commit changes on next vblank */
|
2011-02-08 04:26:52 +08:00
|
|
|
I915_WRITE(CURBASE(pipe), base);
|
2010-08-07 18:01:38 +08:00
|
|
|
}
|
|
|
|
|
2011-10-13 02:10:21 +08:00
|
|
|
static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
bool visible = base != 0;
|
|
|
|
|
|
|
|
if (intel_crtc->cursor_visible != visible) {
|
|
|
|
uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
|
|
|
|
if (base) {
|
|
|
|
cntl &= ~CURSOR_MODE;
|
|
|
|
cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
|
|
|
|
} else {
|
|
|
|
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
|
|
|
|
cntl |= CURSOR_MODE_DISABLE;
|
|
|
|
}
|
2013-01-19 01:11:38 +08:00
|
|
|
if (IS_HASWELL(dev))
|
|
|
|
cntl |= CURSOR_PIPE_CSC_ENABLE;
|
2011-10-13 02:10:21 +08:00
|
|
|
I915_WRITE(CURCNTR_IVB(pipe), cntl);
|
|
|
|
|
|
|
|
intel_crtc->cursor_visible = visible;
|
|
|
|
}
|
|
|
|
/* and commit changes on next vblank */
|
|
|
|
I915_WRITE(CURBASE_IVB(pipe), base);
|
|
|
|
}
|
|
|
|
|
2010-07-09 15:45:04 +08:00
|
|
|
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
|
2010-09-13 20:54:26 +08:00
|
|
|
static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
|
|
|
bool on)
|
2010-07-09 15:45:04 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int x = intel_crtc->cursor_x;
|
|
|
|
int y = intel_crtc->cursor_y;
|
2010-08-07 18:01:38 +08:00
|
|
|
u32 base, pos;
|
2010-07-09 15:45:04 +08:00
|
|
|
bool visible;
|
|
|
|
|
|
|
|
pos = 0;
|
|
|
|
|
2010-09-13 20:54:26 +08:00
|
|
|
if (on && crtc->enabled && crtc->fb) {
|
2010-07-09 15:45:04 +08:00
|
|
|
base = intel_crtc->cursor_addr;
|
|
|
|
if (x > (int) crtc->fb->width)
|
|
|
|
base = 0;
|
|
|
|
|
|
|
|
if (y > (int) crtc->fb->height)
|
|
|
|
base = 0;
|
|
|
|
} else
|
|
|
|
base = 0;
|
|
|
|
|
|
|
|
if (x < 0) {
|
|
|
|
if (x + intel_crtc->cursor_width < 0)
|
|
|
|
base = 0;
|
|
|
|
|
|
|
|
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
|
|
|
x = -x;
|
|
|
|
}
|
|
|
|
pos |= x << CURSOR_X_SHIFT;
|
|
|
|
|
|
|
|
if (y < 0) {
|
|
|
|
if (y + intel_crtc->cursor_height < 0)
|
|
|
|
base = 0;
|
|
|
|
|
|
|
|
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
|
|
|
y = -y;
|
|
|
|
}
|
|
|
|
pos |= y << CURSOR_Y_SHIFT;
|
|
|
|
|
|
|
|
visible = base != 0;
|
2010-08-07 18:01:38 +08:00
|
|
|
if (!visible && !intel_crtc->cursor_visible)
|
2010-07-09 15:45:04 +08:00
|
|
|
return;
|
|
|
|
|
2012-04-14 04:08:48 +08:00
|
|
|
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
|
2011-10-13 02:10:21 +08:00
|
|
|
I915_WRITE(CURPOS_IVB(pipe), pos);
|
|
|
|
ivb_update_cursor(crtc, base);
|
|
|
|
} else {
|
|
|
|
I915_WRITE(CURPOS(pipe), pos);
|
|
|
|
if (IS_845G(dev) || IS_I865G(dev))
|
|
|
|
i845_update_cursor(crtc, base);
|
|
|
|
else
|
|
|
|
i9xx_update_cursor(crtc, base);
|
|
|
|
}
|
2010-07-09 15:45:04 +08:00
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_file *file,
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
uint32_t handle,
|
|
|
|
uint32_t width, uint32_t height)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj;
|
2010-07-09 15:45:04 +08:00
|
|
|
uint32_t addr;
|
2008-12-18 11:14:59 +08:00
|
|
|
int ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
/* if we want to turn off the cursor ignore width and height */
|
|
|
|
if (!handle) {
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("cursor off\n");
|
2008-12-18 11:14:59 +08:00
|
|
|
addr = 0;
|
2010-11-09 03:18:58 +08:00
|
|
|
obj = NULL;
|
2009-02-23 08:12:15 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2008-12-18 11:14:59 +08:00
|
|
|
goto finish;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Currently we only support 64x64 cursors */
|
|
|
|
if (width != 64 || height != 64) {
|
|
|
|
DRM_ERROR("we currently only support 64x64 cursors\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2010-11-09 03:18:58 +08:00
|
|
|
obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
|
2011-02-19 19:31:06 +08:00
|
|
|
if (&obj->base == NULL)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
return -ENOENT;
|
|
|
|
|
2010-11-09 03:18:58 +08:00
|
|
|
if (obj->base.size < width * height * 4) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
DRM_ERROR("buffer is to small\n");
|
2009-01-15 12:03:07 +08:00
|
|
|
ret = -ENOMEM;
|
|
|
|
goto fail;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2008-12-30 18:31:46 +08:00
|
|
|
/* we only need to pin inside GTT if cursor is non-phy */
|
2009-02-14 09:56:49 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2009-12-17 04:16:17 +08:00
|
|
|
if (!dev_priv->info->cursor_needs_physical) {
|
2013-03-05 22:52:39 +08:00
|
|
|
unsigned alignment;
|
|
|
|
|
2010-11-11 00:40:20 +08:00
|
|
|
if (obj->tiling_mode) {
|
|
|
|
DRM_ERROR("cursor cannot be tiled\n");
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto fail_locked;
|
|
|
|
}
|
|
|
|
|
2013-03-05 22:52:39 +08:00
|
|
|
/* 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))
|
|
|
|
alignment = 64*1024;
|
|
|
|
|
|
|
|
ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
|
2010-06-02 15:30:48 +08:00
|
|
|
if (ret) {
|
|
|
|
DRM_ERROR("failed to move cursor bo into the GTT\n");
|
2011-04-14 16:41:17 +08:00
|
|
|
goto fail_locked;
|
2010-06-02 15:30:48 +08:00
|
|
|
}
|
|
|
|
|
2010-11-11 00:40:20 +08:00
|
|
|
ret = i915_gem_object_put_fence(obj);
|
|
|
|
if (ret) {
|
2011-04-14 16:41:17 +08:00
|
|
|
DRM_ERROR("failed to release fence for cursor");
|
2010-11-11 00:40:20 +08:00
|
|
|
goto fail_unpin;
|
|
|
|
}
|
|
|
|
|
2010-11-09 03:18:58 +08:00
|
|
|
addr = obj->gtt_offset;
|
2008-12-30 18:31:46 +08:00
|
|
|
} else {
|
2010-08-07 18:01:39 +08:00
|
|
|
int align = IS_I830(dev) ? 16 * 1024 : 256;
|
2010-11-09 03:18:58 +08:00
|
|
|
ret = i915_gem_attach_phys_object(dev, obj,
|
2010-08-07 18:01:39 +08:00
|
|
|
(intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
|
|
|
|
align);
|
2008-12-30 18:31:46 +08:00
|
|
|
if (ret) {
|
|
|
|
DRM_ERROR("failed to attach phys object\n");
|
2009-02-14 09:56:49 +08:00
|
|
|
goto fail_locked;
|
2008-12-30 18:31:46 +08:00
|
|
|
}
|
2010-11-09 03:18:58 +08:00
|
|
|
addr = obj->phys_obj->handle->busaddr;
|
2008-12-18 11:14:59 +08:00
|
|
|
}
|
|
|
|
|
2010-09-17 07:32:17 +08:00
|
|
|
if (IS_GEN2(dev))
|
2009-05-21 04:47:08 +08:00
|
|
|
I915_WRITE(CURSIZE, (height << 12) | width);
|
|
|
|
|
2008-12-18 11:14:59 +08:00
|
|
|
finish:
|
|
|
|
if (intel_crtc->cursor_bo) {
|
2009-12-17 04:16:17 +08:00
|
|
|
if (dev_priv->info->cursor_needs_physical) {
|
2010-11-09 03:18:58 +08:00
|
|
|
if (intel_crtc->cursor_bo != obj)
|
2008-12-30 18:31:46 +08:00
|
|
|
i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
|
|
|
|
} else
|
|
|
|
i915_gem_object_unpin(intel_crtc->cursor_bo);
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
|
2008-12-18 11:14:59 +08:00
|
|
|
}
|
2009-09-11 06:28:06 +08:00
|
|
|
|
2009-02-14 09:56:49 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2008-12-18 11:14:59 +08:00
|
|
|
|
|
|
|
intel_crtc->cursor_addr = addr;
|
2010-11-09 03:18:58 +08:00
|
|
|
intel_crtc->cursor_bo = obj;
|
2010-07-09 15:45:04 +08:00
|
|
|
intel_crtc->cursor_width = width;
|
|
|
|
intel_crtc->cursor_height = height;
|
|
|
|
|
2013-04-23 22:27:08 +08:00
|
|
|
intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
|
2008-12-18 11:14:59 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
return 0;
|
2010-06-02 15:30:48 +08:00
|
|
|
fail_unpin:
|
2010-11-09 03:18:58 +08:00
|
|
|
i915_gem_object_unpin(obj);
|
2009-02-14 09:56:49 +08:00
|
|
|
fail_locked:
|
2009-01-15 12:03:07 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2010-02-09 13:49:12 +08:00
|
|
|
fail:
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
2009-01-15 12:03:07 +08:00
|
|
|
return ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
2010-07-09 15:45:04 +08:00
|
|
|
intel_crtc->cursor_x = x;
|
|
|
|
intel_crtc->cursor_y = y;
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2013-04-23 22:27:08 +08:00
|
|
|
intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Sets the color ramps on behalf of RandR */
|
|
|
|
void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
|
|
|
u16 blue, int regno)
|
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
intel_crtc->lut_r[regno] = red >> 8;
|
|
|
|
intel_crtc->lut_g[regno] = green >> 8;
|
|
|
|
intel_crtc->lut_b[regno] = blue >> 8;
|
|
|
|
}
|
|
|
|
|
2009-10-06 11:54:01 +08:00
|
|
|
void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
|
|
|
|
u16 *blue, int regno)
|
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
*red = intel_crtc->lut_r[regno] << 8;
|
|
|
|
*green = intel_crtc->lut_g[regno] << 8;
|
|
|
|
*blue = intel_crtc->lut_b[regno] << 8;
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
2010-08-03 08:33:19 +08:00
|
|
|
u16 *blue, uint32_t start, uint32_t size)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2010-08-03 08:33:19 +08:00
|
|
|
int end = (start + size > 256) ? 256 : start + size, i;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
2010-08-03 08:33:19 +08:00
|
|
|
for (i = start; i < end; i++) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
intel_crtc->lut_r[i] = red[i] >> 8;
|
|
|
|
intel_crtc->lut_g[i] = green[i] >> 8;
|
|
|
|
intel_crtc->lut_b[i] = blue[i] >> 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* VESA 640x480x72Hz mode to set on the pipe */
|
|
|
|
static struct drm_display_mode load_detect_mode = {
|
|
|
|
DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
|
|
|
|
704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
|
|
|
|
};
|
|
|
|
|
2011-04-19 15:36:26 +08:00
|
|
|
static struct drm_framebuffer *
|
|
|
|
intel_framebuffer_create(struct drm_device *dev,
|
2011-11-15 06:51:28 +08:00
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
2011-04-19 15:36:26 +08:00
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct intel_framebuffer *intel_fb;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
|
|
|
|
if (!intel_fb) {
|
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
|
|
|
|
if (ret) {
|
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
|
|
|
kfree(intel_fb);
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
return &intel_fb->base;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32
|
|
|
|
intel_framebuffer_pitch_for_width(int width, int bpp)
|
|
|
|
{
|
|
|
|
u32 pitch = DIV_ROUND_UP(width * bpp, 8);
|
|
|
|
return ALIGN(pitch, 64);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32
|
|
|
|
intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
|
|
|
|
{
|
|
|
|
u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
|
|
|
|
return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
|
intel_framebuffer_create_for_mode(struct drm_device *dev,
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
int depth, int bpp)
|
|
|
|
{
|
|
|
|
struct drm_i915_gem_object *obj;
|
2012-11-06 06:25:07 +08:00
|
|
|
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
2011-04-19 15:36:26 +08:00
|
|
|
|
|
|
|
obj = i915_gem_alloc_object(dev,
|
|
|
|
intel_framebuffer_size_for_mode(mode, bpp));
|
|
|
|
if (obj == NULL)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
mode_cmd.width = mode->hdisplay;
|
|
|
|
mode_cmd.height = mode->vdisplay;
|
2011-11-15 06:51:28 +08:00
|
|
|
mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
|
|
|
|
bpp);
|
2012-02-23 23:33:40 +08:00
|
|
|
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
|
2011-04-19 15:36:26 +08:00
|
|
|
|
|
|
|
return intel_framebuffer_create(dev, &mode_cmd, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
|
mode_fits_in_fbdev(struct drm_device *dev,
|
|
|
|
struct drm_display_mode *mode)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct drm_i915_gem_object *obj;
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
|
|
|
if (dev_priv->fbdev == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
obj = dev_priv->fbdev->ifb.obj;
|
|
|
|
if (obj == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
fb = &dev_priv->fbdev->ifb.base;
|
2011-12-20 06:06:49 +08:00
|
|
|
if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
|
|
|
|
fb->bits_per_pixel))
|
2011-04-19 15:36:26 +08:00
|
|
|
return NULL;
|
|
|
|
|
2011-12-20 06:06:49 +08:00
|
|
|
if (obj->base.size < mode->vdisplay * fb->pitches[0])
|
2011-04-19 15:36:26 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return fb;
|
|
|
|
}
|
|
|
|
|
2012-08-13 03:20:10 +08:00
|
|
|
bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
2011-04-20 06:10:58 +08:00
|
|
|
struct drm_display_mode *mode,
|
2011-04-20 06:18:09 +08:00
|
|
|
struct intel_load_detect_pipe *old)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc;
|
2012-08-13 03:20:10 +08:00
|
|
|
struct intel_encoder *intel_encoder =
|
|
|
|
intel_attached_encoder(connector);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct drm_crtc *possible_crtc;
|
2010-09-09 22:14:28 +08:00
|
|
|
struct drm_encoder *encoder = &intel_encoder->base;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct drm_crtc *crtc = NULL;
|
|
|
|
struct drm_device *dev = encoder->dev;
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
struct drm_framebuffer *fb;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int i = -1;
|
|
|
|
|
2011-04-19 15:36:26 +08:00
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
|
|
|
connector->base.id, drm_get_connector_name(connector),
|
|
|
|
encoder->base.id, drm_get_encoder_name(encoder));
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/*
|
|
|
|
* Algorithm gets a little messy:
|
2011-04-20 06:21:12 +08:00
|
|
|
*
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
* - if the connector already has an assigned crtc, use it (but make
|
|
|
|
* sure it's on first)
|
2011-04-20 06:21:12 +08:00
|
|
|
*
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
* - 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 */
|
|
|
|
if (encoder->crtc) {
|
|
|
|
crtc = encoder->crtc;
|
2011-04-20 06:18:09 +08:00
|
|
|
|
2012-12-12 07:35:33 +08:00
|
|
|
mutex_lock(&crtc->mutex);
|
|
|
|
|
2012-08-13 01:27:11 +08:00
|
|
|
old->dpms_mode = connector->dpms;
|
2011-04-20 06:18:09 +08:00
|
|
|
old->load_detect_temp = false;
|
|
|
|
|
|
|
|
/* Make sure the crtc and connector are running */
|
2012-08-13 01:27:11 +08:00
|
|
|
if (connector->dpms != DRM_MODE_DPMS_ON)
|
|
|
|
connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
|
2011-04-20 06:18:09 +08:00
|
|
|
|
2011-04-20 06:10:58 +08:00
|
|
|
return true;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Find an unused one (if possible) */
|
|
|
|
list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
i++;
|
|
|
|
if (!(encoder->possible_crtcs & (1 << i)))
|
|
|
|
continue;
|
|
|
|
if (!possible_crtc->enabled) {
|
|
|
|
crtc = possible_crtc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we didn't find an unused CRTC, don't use any.
|
|
|
|
*/
|
|
|
|
if (!crtc) {
|
2011-04-20 06:10:58 +08:00
|
|
|
DRM_DEBUG_KMS("no pipe available for load-detect\n");
|
|
|
|
return false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-12-12 07:35:33 +08:00
|
|
|
mutex_lock(&crtc->mutex);
|
2012-07-09 16:40:58 +08:00
|
|
|
intel_encoder->new_crtc = to_intel_crtc(crtc);
|
|
|
|
to_intel_connector(connector)->new_encoder = intel_encoder;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
2012-08-13 01:27:11 +08:00
|
|
|
old->dpms_mode = connector->dpms;
|
2011-04-20 06:18:09 +08:00
|
|
|
old->load_detect_temp = true;
|
2011-04-19 15:36:26 +08:00
|
|
|
old->release_fb = NULL;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-04-20 14:25:26 +08:00
|
|
|
if (!mode)
|
|
|
|
mode = &load_detect_mode;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-04-19 15:36:26 +08:00
|
|
|
/* 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/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
fb = mode_fits_in_fbdev(dev, mode);
|
|
|
|
if (fb == NULL) {
|
2011-04-19 15:36:26 +08:00
|
|
|
DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
|
|
|
|
old->release_fb = fb;
|
2011-04-19 15:36:26 +08:00
|
|
|
} else
|
|
|
|
DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
if (IS_ERR(fb)) {
|
2011-04-19 15:36:26 +08:00
|
|
|
DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
|
2012-12-12 07:35:33 +08:00
|
|
|
mutex_unlock(&crtc->mutex);
|
2012-11-06 06:25:08 +08:00
|
|
|
return false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 00:08:43 +08:00
|
|
|
if (intel_set_mode(crtc, mode, 0, 0, fb)) {
|
2011-04-20 14:25:26 +08:00
|
|
|
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
|
2011-04-19 15:36:26 +08:00
|
|
|
if (old->release_fb)
|
|
|
|
old->release_fb->funcs->destroy(old->release_fb);
|
2012-12-12 07:35:33 +08:00
|
|
|
mutex_unlock(&crtc->mutex);
|
2012-11-06 06:25:08 +08:00
|
|
|
return false;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2011-04-20 06:10:58 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
/* let the connector get through one full cycle before testing */
|
2010-08-19 04:20:54 +08:00
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
2011-04-20 06:10:58 +08:00
|
|
|
return true;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-08-13 03:20:10 +08:00
|
|
|
void intel_release_load_detect_pipe(struct drm_connector *connector,
|
2011-04-20 06:18:09 +08:00
|
|
|
struct intel_load_detect_pipe *old)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-08-13 03:20:10 +08:00
|
|
|
struct intel_encoder *intel_encoder =
|
|
|
|
intel_attached_encoder(connector);
|
2010-09-09 22:14:28 +08:00
|
|
|
struct drm_encoder *encoder = &intel_encoder->base;
|
2012-12-12 07:35:33 +08:00
|
|
|
struct drm_crtc *crtc = encoder->crtc;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-04-19 15:36:26 +08:00
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
|
|
|
connector->base.id, drm_get_connector_name(connector),
|
|
|
|
encoder->base.id, drm_get_encoder_name(encoder));
|
|
|
|
|
2011-04-20 06:18:09 +08:00
|
|
|
if (old->load_detect_temp) {
|
2012-07-09 16:40:58 +08:00
|
|
|
to_intel_connector(connector)->new_encoder = NULL;
|
|
|
|
intel_encoder->new_crtc = NULL;
|
|
|
|
intel_set_mode(crtc, NULL, 0, 0, NULL);
|
2011-04-19 15:36:26 +08:00
|
|
|
|
drm: revamp framebuffer cleanup interfaces
We have two classes of framebuffer
- Created by the driver (atm only for fbdev), and the driver holds
onto the last reference count until destruction.
- Created by userspace and associated with a given fd. These
framebuffers will be reaped when their assoiciated fb is closed.
Now these two cases are set up differently, the framebuffers are on
different lists and hence destruction needs to clean up different
things. Also, for userspace framebuffers we remove them from any
current usage, whereas for internal framebuffers it is assumed that
the driver has done this already.
Long story short, we need two different ways to cleanup such drivers.
Three functions are involved in total:
- drm_framebuffer_remove: Convenience function which removes the fb
from all active usage and then drops the passed-in reference.
- drm_framebuffer_unregister_private: Will remove driver-private
framebuffers from relevant lists and drop the corresponding
references. Should be called for driver-private framebuffers before
dropping the last reference (or like for a lot of the drivers where
the fbdev is embedded someplace else, before doing the cleanup
manually).
- drm_framebuffer_cleanup: Final cleanup for both classes of fbs,
should be called by the driver's ->destroy callback once the last
reference is gone.
This patch just rolls out the new interfaces and updates all drivers
(by adding calls to drm_framebuffer_unregister_private at all the
right places)- no functional changes yet. Follow-on patches will move
drm core code around and update the lifetime management for
framebuffers, so that we are no longer required to keep framebuffers
alive by locking mode_config.mutex.
I've also updated the kerneldoc already.
vmwgfx seems to again be a bit special, at least I haven't figured out
how the fbdev support in that driver works. It smells like it's
external though.
v2: The i915 driver creates another private framebuffer in the
load-detect code. Adjust its cleanup code, too.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 03:42:17 +08:00
|
|
|
if (old->release_fb) {
|
|
|
|
drm_framebuffer_unregister_private(old->release_fb);
|
|
|
|
drm_framebuffer_unreference(old->release_fb);
|
|
|
|
}
|
2011-04-19 15:36:26 +08:00
|
|
|
|
2013-01-24 00:25:09 +08:00
|
|
|
mutex_unlock(&crtc->mutex);
|
2011-04-21 16:32:11 +08:00
|
|
|
return;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-03-26 02:48:48 +08:00
|
|
|
/* Switch crtc and encoder back off if necessary */
|
2012-08-13 01:27:11 +08:00
|
|
|
if (old->dpms_mode != DRM_MODE_DPMS_ON)
|
|
|
|
connector->funcs->dpms(connector, old->dpms_mode);
|
2012-12-12 07:35:33 +08:00
|
|
|
|
|
|
|
mutex_unlock(&crtc->mutex);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns the clock of the currently programmed mode of the given pipe. */
|
|
|
|
static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2011-02-18 02:40:53 +08:00
|
|
|
u32 dpll = I915_READ(DPLL(pipe));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
u32 fp;
|
|
|
|
intel_clock_t clock;
|
|
|
|
|
|
|
|
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
|
2011-04-23 05:17:21 +08:00
|
|
|
fp = I915_READ(FP0(pipe));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
else
|
2011-04-23 05:17:21 +08:00
|
|
|
fp = I915_READ(FP1(pipe));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
2009-12-04 06:14:42 +08:00
|
|
|
if (IS_PINEVIEW(dev)) {
|
|
|
|
clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
|
|
|
|
clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
2009-02-23 15:19:16 +08:00
|
|
|
} else {
|
|
|
|
clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
|
|
|
|
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
|
|
|
}
|
|
|
|
|
2010-09-17 07:32:17 +08:00
|
|
|
if (!IS_GEN2(dev)) {
|
2009-12-04 06:14:42 +08:00
|
|
|
if (IS_PINEVIEW(dev))
|
|
|
|
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
|
|
|
|
DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
|
2009-02-23 15:19:16 +08:00
|
|
|
else
|
|
|
|
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
|
|
|
|
|
|
|
switch (dpll & DPLL_MODE_MASK) {
|
|
|
|
case DPLLB_MODE_DAC_SERIAL:
|
|
|
|
clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
|
|
|
|
5 : 10;
|
|
|
|
break;
|
|
|
|
case DPLLB_MODE_LVDS:
|
|
|
|
clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
|
|
|
|
7 : 14;
|
|
|
|
break;
|
|
|
|
default:
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
"mode\n", (int)(dpll & DPLL_MODE_MASK));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: Handle the 100Mhz refclk */
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, 96000, &clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} else {
|
|
|
|
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
|
|
|
|
|
|
|
|
if (is_lvds) {
|
|
|
|
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
|
|
|
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
|
|
|
clock.p2 = 14;
|
|
|
|
|
|
|
|
if ((dpll & PLL_REF_INPUT_MASK) ==
|
|
|
|
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
|
|
|
|
/* XXX: might not be 66MHz */
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, 66000, &clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} else
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, 48000, &clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} else {
|
|
|
|
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
|
|
|
clock.p1 = 2;
|
|
|
|
else {
|
|
|
|
clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
|
|
|
|
DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
|
|
|
|
}
|
|
|
|
if (dpll & PLL_P2_DIVIDE_BY_4)
|
|
|
|
clock.p2 = 4;
|
|
|
|
else
|
|
|
|
clock.p2 = 2;
|
|
|
|
|
2009-02-23 15:19:16 +08:00
|
|
|
intel_clock(dev, 48000, &clock);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return clock.dot;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the currently programmed mode of the given pipe. */
|
|
|
|
struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc)
|
|
|
|
{
|
2011-02-18 02:40:53 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-04-18 02:15:07 +08:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct drm_display_mode *mode;
|
2012-10-24 04:30:02 +08:00
|
|
|
int htot = I915_READ(HTOTAL(cpu_transcoder));
|
|
|
|
int hsync = I915_READ(HSYNC(cpu_transcoder));
|
|
|
|
int vtot = I915_READ(VTOTAL(cpu_transcoder));
|
|
|
|
int vsync = I915_READ(VSYNC(cpu_transcoder));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
|
|
|
if (!mode)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mode->clock = intel_crtc_clock_get(dev, crtc);
|
|
|
|
mode->hdisplay = (htot & 0xffff) + 1;
|
|
|
|
mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
|
|
|
|
mode->hsync_start = (hsync & 0xffff) + 1;
|
|
|
|
mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
|
|
|
|
mode->vdisplay = (vtot & 0xffff) + 1;
|
|
|
|
mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
|
|
|
|
mode->vsync_start = (vsync & 0xffff) + 1;
|
|
|
|
mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
|
|
|
|
|
|
|
|
drm_mode_set_name(mode);
|
|
|
|
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
2010-08-21 03:40:52 +08:00
|
|
|
static void intel_increase_pllclock(struct drm_crtc *crtc)
|
2009-08-18 04:31:43 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
int pipe = intel_crtc->pipe;
|
2010-12-31 01:36:39 +08:00
|
|
|
int dpll_reg = DPLL(pipe);
|
|
|
|
int dpll;
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2009-10-23 07:11:14 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev))
|
2009-08-18 04:31:43 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!dev_priv->lvds_downclock_avail)
|
|
|
|
return;
|
|
|
|
|
2010-12-31 01:36:39 +08:00
|
|
|
dpll = I915_READ(dpll_reg);
|
2009-08-18 04:31:43 +08:00
|
|
|
if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
|
2009-10-09 11:39:40 +08:00
|
|
|
DRM_DEBUG_DRIVER("upclocking LVDS\n");
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-02-14 02:14:51 +08:00
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
2009-08-18 04:31:43 +08:00
|
|
|
|
|
|
|
dpll &= ~DISPLAY_RATE_SELECT_FPA1;
|
|
|
|
I915_WRITE(dpll_reg, dpll);
|
2010-08-19 04:20:54 +08:00
|
|
|
intel_wait_for_vblank(dev, pipe);
|
2010-12-31 01:36:39 +08:00
|
|
|
|
2009-08-18 04:31:43 +08:00
|
|
|
dpll = I915_READ(dpll_reg);
|
|
|
|
if (dpll & DISPLAY_RATE_SELECT_FPA1)
|
2009-10-09 11:39:40 +08:00
|
|
|
DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void intel_decrease_pllclock(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
2009-10-23 07:11:14 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev))
|
2009-08-18 04:31:43 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!dev_priv->lvds_downclock_avail)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since this is called by a timer, we should never get here in
|
|
|
|
* the manual case.
|
|
|
|
*/
|
|
|
|
if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
|
2012-05-07 17:30:46 +08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
int dpll_reg = DPLL(pipe);
|
|
|
|
int dpll;
|
2011-04-13 01:06:51 +08:00
|
|
|
|
2009-10-09 11:39:40 +08:00
|
|
|
DRM_DEBUG_DRIVER("downclocking LVDS\n");
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-02-14 02:14:51 +08:00
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-05-07 17:30:46 +08:00
|
|
|
dpll = I915_READ(dpll_reg);
|
2009-08-18 04:31:43 +08:00
|
|
|
dpll |= DISPLAY_RATE_SELECT_FPA1;
|
|
|
|
I915_WRITE(dpll_reg, dpll);
|
2010-08-19 04:20:54 +08:00
|
|
|
intel_wait_for_vblank(dev, pipe);
|
2009-08-18 04:31:43 +08:00
|
|
|
dpll = I915_READ(dpll_reg);
|
|
|
|
if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
|
2009-10-09 11:39:40 +08:00
|
|
|
DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-07-21 19:31:41 +08:00
|
|
|
void intel_mark_busy(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
i915_update_gfx_val(dev->dev_private);
|
|
|
|
}
|
|
|
|
|
|
|
|
void intel_mark_idle(struct drm_device *dev)
|
2009-08-18 04:31:43 +08:00
|
|
|
{
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
|
|
|
if (!i915_powersave)
|
|
|
|
return;
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
if (!crtc->fb)
|
|
|
|
continue;
|
|
|
|
|
2013-01-08 19:02:57 +08:00
|
|
|
intel_decrease_pllclock(crtc);
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-08 19:02:57 +08:00
|
|
|
void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
|
2009-08-18 04:31:43 +08:00
|
|
|
{
|
2012-07-21 19:31:41 +08:00
|
|
|
struct drm_device *dev = obj->base.dev;
|
|
|
|
struct drm_crtc *crtc;
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-07-21 19:31:41 +08:00
|
|
|
if (!i915_powersave)
|
2012-05-03 22:47:57 +08:00
|
|
|
return;
|
|
|
|
|
2009-08-18 04:31:43 +08:00
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
if (!crtc->fb)
|
|
|
|
continue;
|
|
|
|
|
2012-07-21 19:31:41 +08:00
|
|
|
if (to_intel_framebuffer(crtc->fb)->obj == obj)
|
2013-01-08 19:02:57 +08:00
|
|
|
intel_increase_pllclock(crtc);
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
static void intel_crtc_destroy(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2010-08-21 04:26:30 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct intel_unpin_work *work;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
work = intel_crtc->unpin_work;
|
|
|
|
intel_crtc->unpin_work = NULL;
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
|
|
|
if (work) {
|
|
|
|
cancel_work_sync(&work->work);
|
|
|
|
kfree(work);
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2013-04-23 22:27:08 +08:00
|
|
|
intel_crtc_cursor_set(crtc, NULL, 0, 0, 0);
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
drm_crtc_cleanup(crtc);
|
2010-08-21 04:26:30 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
kfree(intel_crtc);
|
|
|
|
}
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
static void intel_unpin_work_fn(struct work_struct *__work)
|
|
|
|
{
|
|
|
|
struct intel_unpin_work *work =
|
|
|
|
container_of(__work, struct intel_unpin_work, work);
|
2012-11-01 17:26:26 +08:00
|
|
|
struct drm_device *dev = work->crtc->dev;
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2012-11-01 17:26:26 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2011-12-14 20:57:08 +08:00
|
|
|
intel_unpin_fb_obj(work->old_fb_obj);
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_unreference(&work->pending_flip_obj->base);
|
|
|
|
drm_gem_object_unreference(&work->old_fb_obj->base);
|
2010-11-11 00:40:20 +08:00
|
|
|
|
2012-11-01 17:26:26 +08:00
|
|
|
intel_update_fbc(dev);
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
|
|
|
|
atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
kfree(work);
|
|
|
|
}
|
|
|
|
|
2010-03-27 01:35:20 +08:00
|
|
|
static void do_intel_finish_page_flip(struct drm_device *dev,
|
2010-12-09 14:00:07 +08:00
|
|
|
struct drm_crtc *crtc)
|
2009-11-19 00:25:18 +08:00
|
|
|
{
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_unpin_work *work;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
/* Ignore early vblank irqs */
|
|
|
|
if (intel_crtc == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
work = intel_crtc->unpin_work;
|
2012-12-03 19:36:30 +08:00
|
|
|
|
|
|
|
/* Ensure we don't miss a work->pending update ... */
|
|
|
|
smp_rmb();
|
|
|
|
|
|
|
|
if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
|
2009-11-19 00:25:18 +08:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-03 19:36:30 +08:00
|
|
|
/* and that the unpin work is consistent wrt ->pending. */
|
|
|
|
smp_rmb();
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
intel_crtc->unpin_work = NULL;
|
|
|
|
|
2012-10-09 03:50:40 +08:00
|
|
|
if (work->event)
|
|
|
|
drm_send_vblank_event(dev, intel_crtc->pipe, work->event);
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2010-12-08 11:07:19 +08:00
|
|
|
drm_vblank_put(dev, intel_crtc->pipe);
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
2012-12-21 04:24:07 +08:00
|
|
|
wake_up_all(&dev_priv->pending_flip_queue);
|
2012-11-01 17:26:26 +08:00
|
|
|
|
|
|
|
queue_work(dev_priv->wq, &work->work);
|
2010-07-02 07:48:37 +08:00
|
|
|
|
|
|
|
trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
|
2009-11-19 00:25:18 +08:00
|
|
|
}
|
|
|
|
|
2010-03-27 01:35:20 +08:00
|
|
|
void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
{
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
|
2010-12-09 14:00:07 +08:00
|
|
|
do_intel_finish_page_flip(dev, crtc);
|
2010-03-27 01:35:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
|
|
|
|
{
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
|
|
|
|
|
2010-12-09 14:00:07 +08:00
|
|
|
do_intel_finish_page_flip(dev, crtc);
|
2010-03-27 01:35:20 +08:00
|
|
|
}
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
void intel_prepare_page_flip(struct drm_device *dev, int plane)
|
|
|
|
{
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc =
|
|
|
|
to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
|
|
|
|
unsigned long flags;
|
|
|
|
|
2012-12-03 19:36:30 +08:00
|
|
|
/* 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().
|
|
|
|
*/
|
2009-11-19 00:25:18 +08:00
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
2012-12-03 19:36:30 +08:00
|
|
|
if (intel_crtc->unpin_work)
|
|
|
|
atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
|
2009-11-19 00:25:18 +08:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
}
|
|
|
|
|
2012-12-03 19:36:30 +08:00
|
|
|
inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
|
|
|
|
{
|
|
|
|
/* Ensure that the work item is consistent when activating it ... */
|
|
|
|
smp_wmb();
|
|
|
|
atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
|
|
|
|
/* and that it is marked active as soon as the irq could fire. */
|
|
|
|
smp_wmb();
|
|
|
|
}
|
|
|
|
|
2011-06-17 00:19:13 +08:00
|
|
|
static int intel_gen2_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
u32 flip_mask;
|
2012-04-27 05:28:05 +08:00
|
|
|
struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
|
2011-06-17 00:19:13 +08:00
|
|
|
int ret;
|
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_ring_begin(ring, 6);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err_unpin;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
|
|
|
/* Can't queue multiple flips, so wait for the previous
|
|
|
|
* one to finish before executing the next.
|
|
|
|
*/
|
|
|
|
if (intel_crtc->plane)
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
|
else
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
|
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
intel_ring_emit(ring, fb->pitches[0]);
|
2012-07-05 18:17:29 +08:00
|
|
|
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, 0); /* aux display base address, unused */
|
2012-12-03 19:36:30 +08:00
|
|
|
|
|
|
|
intel_mark_page_flip_active(intel_crtc);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_advance(ring);
|
2012-04-18 02:35:53 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
intel_unpin_fb_obj(obj);
|
|
|
|
err:
|
2011-06-17 00:19:13 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_gen3_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
u32 flip_mask;
|
2012-04-27 05:28:05 +08:00
|
|
|
struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
|
2011-06-17 00:19:13 +08:00
|
|
|
int ret;
|
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_ring_begin(ring, 6);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err_unpin;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
|
|
|
if (intel_crtc->plane)
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
|
else
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
|
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
|
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
intel_ring_emit(ring, fb->pitches[0]);
|
2012-07-05 18:17:29 +08:00
|
|
|
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
|
2012-12-03 19:36:30 +08:00
|
|
|
intel_mark_page_flip_active(intel_crtc);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_advance(ring);
|
2012-04-18 02:35:53 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
intel_unpin_fb_obj(obj);
|
|
|
|
err:
|
2011-06-17 00:19:13 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_gen4_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
uint32_t pf, pipesrc;
|
2012-04-27 05:28:05 +08:00
|
|
|
struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
|
2011-06-17 00:19:13 +08:00
|
|
|
int ret;
|
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_ring_begin(ring, 4);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err_unpin;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
intel_ring_emit(ring, fb->pitches[0]);
|
2012-07-05 18:17:30 +08:00
|
|
|
intel_ring_emit(ring,
|
|
|
|
(obj->gtt_offset + intel_crtc->dspaddr_offset) |
|
|
|
|
obj->tiling_mode);
|
2011-06-17 00:19:13 +08:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, pf | pipesrc);
|
2012-12-03 19:36:30 +08:00
|
|
|
|
|
|
|
intel_mark_page_flip_active(intel_crtc);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_advance(ring);
|
2012-04-18 02:35:53 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
intel_unpin_fb_obj(obj);
|
|
|
|
err:
|
2011-06-17 00:19:13 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_gen6_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-04-27 05:28:05 +08:00
|
|
|
struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
|
2011-06-17 00:19:13 +08:00
|
|
|
uint32_t pf, pipesrc;
|
|
|
|
int ret;
|
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
ret = intel_ring_begin(ring, 4);
|
2011-06-17 00:19:13 +08:00
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err_unpin;
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
|
2012-07-05 18:17:30 +08:00
|
|
|
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2011-06-17 00:19:13 +08:00
|
|
|
|
2012-05-07 17:30:46 +08:00
|
|
|
/* 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;
|
2011-06-17 00:19:13 +08:00
|
|
|
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_emit(ring, pf | pipesrc);
|
2012-12-03 19:36:30 +08:00
|
|
|
|
|
|
|
intel_mark_page_flip_active(intel_crtc);
|
2012-04-27 05:28:05 +08:00
|
|
|
intel_ring_advance(ring);
|
2012-04-18 02:35:53 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
intel_unpin_fb_obj(obj);
|
|
|
|
err:
|
2011-06-17 00:19:13 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-17 03:18:54 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static int intel_gen7_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
|
2012-05-23 20:02:00 +08:00
|
|
|
uint32_t plane_bit = 0;
|
2011-06-17 03:18:54 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
|
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err;
|
2011-06-17 03:18:54 +08:00
|
|
|
|
2012-05-23 20:02:00 +08:00
|
|
|
switch(intel_crtc->plane) {
|
|
|
|
case PLANE_A:
|
|
|
|
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
|
|
|
|
break;
|
|
|
|
case PLANE_B:
|
|
|
|
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B;
|
|
|
|
break;
|
|
|
|
case PLANE_C:
|
|
|
|
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ONCE(1, "unknown plane in flip command\n");
|
|
|
|
ret = -ENODEV;
|
2012-06-19 06:03:38 +08:00
|
|
|
goto err_unpin;
|
2012-05-23 20:02:00 +08:00
|
|
|
}
|
|
|
|
|
2011-06-17 03:18:54 +08:00
|
|
|
ret = intel_ring_begin(ring, 4);
|
|
|
|
if (ret)
|
2012-04-18 02:35:53 +08:00
|
|
|
goto err_unpin;
|
2011-06-17 03:18:54 +08:00
|
|
|
|
2012-05-23 20:02:00 +08:00
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
|
2011-12-20 06:06:49 +08:00
|
|
|
intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
|
2012-07-05 18:17:30 +08:00
|
|
|
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
|
2011-06-17 03:18:54 +08:00
|
|
|
intel_ring_emit(ring, (MI_NOOP));
|
2012-12-03 19:36:30 +08:00
|
|
|
|
|
|
|
intel_mark_page_flip_active(intel_crtc);
|
2011-06-17 03:18:54 +08:00
|
|
|
intel_ring_advance(ring);
|
2012-04-18 02:35:53 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unpin:
|
|
|
|
intel_unpin_fb_obj(obj);
|
|
|
|
err:
|
2011-06-17 03:18:54 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-17 00:19:13 +08:00
|
|
|
static int intel_default_queue_flip(struct drm_device *dev,
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct drm_pending_vblank_event *event)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-02-22 22:53:38 +08:00
|
|
|
struct drm_framebuffer *old_fb = crtc->fb;
|
|
|
|
struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
|
2009-11-19 00:25:18 +08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
struct intel_unpin_work *work;
|
2011-06-17 00:19:13 +08:00
|
|
|
unsigned long flags;
|
2010-08-08 17:15:59 +08:00
|
|
|
int ret;
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2012-05-25 02:08:59 +08:00
|
|
|
/* Can't change pixel format via MI display flips. */
|
|
|
|
if (fb->pixel_format != crtc->fb->pixel_format)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TILEOFF/LINOFF registers can't be changed via MI display flips.
|
|
|
|
* Note that pitch changes could also affect these register.
|
|
|
|
*/
|
|
|
|
if (INTEL_INFO(dev)->gen > 3 &&
|
|
|
|
(fb->offsets[0] != crtc->fb->offsets[0] ||
|
|
|
|
fb->pitches[0] != crtc->fb->pitches[0]))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
|
|
if (work == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
work->event = event;
|
2012-11-01 17:26:26 +08:00
|
|
|
work->crtc = crtc;
|
2013-02-22 22:53:38 +08:00
|
|
|
work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
|
2009-11-19 00:25:18 +08:00
|
|
|
INIT_WORK(&work->work, intel_unpin_work_fn);
|
|
|
|
|
2011-08-30 00:45:28 +08:00
|
|
|
ret = drm_vblank_get(dev, intel_crtc->pipe);
|
|
|
|
if (ret)
|
|
|
|
goto free_work;
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
/* We borrow the event spin lock for protecting unpin_work */
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
if (intel_crtc->unpin_work) {
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
kfree(work);
|
2011-08-30 00:45:28 +08:00
|
|
|
drm_vblank_put(dev, intel_crtc->pipe);
|
2010-05-27 20:18:13 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
|
2009-11-19 00:25:18 +08:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
intel_crtc->unpin_work = work;
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
2012-11-01 17:26:26 +08:00
|
|
|
if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
|
|
|
|
flush_workqueue(dev_priv->wq);
|
|
|
|
|
2012-05-23 18:13:58 +08:00
|
|
|
ret = i915_mutex_lock_interruptible(dev);
|
|
|
|
if (ret)
|
|
|
|
goto cleanup;
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2010-02-11 07:09:44 +08:00
|
|
|
/* Reference the objects for the scheduled work. */
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_reference(&work->old_fb_obj->base);
|
|
|
|
drm_gem_object_reference(&obj->base);
|
2009-11-19 00:25:18 +08:00
|
|
|
|
|
|
|
crtc->fb = fb;
|
2010-06-07 21:03:04 +08:00
|
|
|
|
2010-10-27 19:45:26 +08:00
|
|
|
work->pending_flip_obj = obj;
|
|
|
|
|
2010-09-02 00:47:52 +08:00
|
|
|
work->enable_stall_check = true;
|
|
|
|
|
2012-11-01 17:26:26 +08:00
|
|
|
atomic_inc(&intel_crtc->unpin_work_count);
|
2013-01-30 00:13:34 +08:00
|
|
|
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
2010-10-27 19:45:26 +08:00
|
|
|
|
2011-06-17 00:19:13 +08:00
|
|
|
ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
|
|
|
|
if (ret)
|
|
|
|
goto cleanup_pending;
|
2009-11-19 00:25:18 +08:00
|
|
|
|
2011-07-08 19:22:41 +08:00
|
|
|
intel_disable_fbc(dev);
|
2012-07-21 19:31:41 +08:00
|
|
|
intel_mark_fb_busy(obj);
|
2009-11-19 00:25:18 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
2010-07-02 07:48:37 +08:00
|
|
|
trace_i915_flip_request(intel_crtc->plane, obj);
|
|
|
|
|
2009-11-19 00:25:18 +08:00
|
|
|
return 0;
|
2010-06-07 21:03:04 +08:00
|
|
|
|
2011-06-17 00:19:13 +08:00
|
|
|
cleanup_pending:
|
2012-11-01 17:26:26 +08:00
|
|
|
atomic_dec(&intel_crtc->unpin_work_count);
|
2013-02-22 22:53:38 +08:00
|
|
|
crtc->fb = old_fb;
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_unreference(&work->old_fb_obj->base);
|
|
|
|
drm_gem_object_unreference(&obj->base);
|
2010-06-07 21:03:04 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
2012-05-23 18:13:58 +08:00
|
|
|
cleanup:
|
2010-06-07 21:03:04 +08:00
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
intel_crtc->unpin_work = NULL;
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
2011-08-30 00:45:28 +08:00
|
|
|
drm_vblank_put(dev, intel_crtc->pipe);
|
|
|
|
free_work:
|
2010-06-07 21:03:04 +08:00
|
|
|
kfree(work);
|
|
|
|
|
|
|
|
return ret;
|
2009-11-19 00:25:18 +08:00
|
|
|
}
|
|
|
|
|
2011-04-13 01:06:51 +08:00
|
|
|
static struct drm_crtc_helper_funcs intel_helper_funcs = {
|
|
|
|
.mode_set_base_atomic = intel_pipe_set_base_atomic,
|
|
|
|
.load_lut = intel_crtc_load_lut,
|
|
|
|
};
|
|
|
|
|
2012-07-09 01:41:43 +08:00
|
|
|
bool intel_encoder_check_is_cloned(struct intel_encoder *encoder)
|
2010-12-03 23:37:31 +08:00
|
|
|
{
|
2012-07-09 01:41:43 +08:00
|
|
|
struct intel_encoder *other_encoder;
|
|
|
|
struct drm_crtc *crtc = &encoder->new_crtc->base;
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-09 01:41:43 +08:00
|
|
|
if (WARN_ON(!crtc))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
list_for_each_entry(other_encoder,
|
|
|
|
&crtc->dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
|
|
|
|
if (&other_encoder->new_crtc->base != crtc ||
|
|
|
|
encoder == other_encoder)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
return true;
|
2012-03-22 23:00:50 +08:00
|
|
|
}
|
|
|
|
|
2012-07-09 01:41:43 +08:00
|
|
|
return false;
|
|
|
|
}
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
|
|
|
|
struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev;
|
|
|
|
struct drm_crtc *tmp;
|
|
|
|
int crtc_mask = 1;
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
WARN(!crtc, "checking null crtc?\n");
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
dev = crtc->dev;
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
|
|
|
|
if (tmp == crtc)
|
|
|
|
break;
|
|
|
|
crtc_mask <<= 1;
|
|
|
|
}
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
if (encoder->possible_crtcs & crtc_mask)
|
|
|
|
return true;
|
|
|
|
return false;
|
2010-12-03 23:37:31 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/**
|
|
|
|
* intel_modeset_update_staged_output_state
|
|
|
|
*
|
|
|
|
* Updates the staged output configuration state, e.g. after we've read out the
|
|
|
|
* current hw state.
|
|
|
|
*/
|
|
|
|
static void intel_modeset_update_staged_output_state(struct drm_device *dev)
|
2011-04-13 01:06:51 +08:00
|
|
|
{
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
2011-04-13 01:06:51 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
connector->new_encoder =
|
|
|
|
to_intel_encoder(connector->base.encoder);
|
|
|
|
}
|
2011-04-13 01:06:51 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
encoder->new_crtc =
|
|
|
|
to_intel_crtc(encoder->base.crtc);
|
|
|
|
}
|
2011-04-13 01:06:51 +08:00
|
|
|
}
|
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/**
|
|
|
|
* intel_modeset_commit_output_state
|
|
|
|
*
|
|
|
|
* This function copies the stage display pipe configuration to the real one.
|
|
|
|
*/
|
|
|
|
static void intel_modeset_commit_output_state(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
2011-04-13 01:06:51 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
connector->base.encoder = &connector->new_encoder->base;
|
|
|
|
}
|
2011-04-13 01:06:51 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
encoder->base.crtc = &encoder->new_crtc->base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-02 19:26:23 +08:00
|
|
|
static void
|
|
|
|
connected_sink_compute_bpp(struct intel_connector * connector,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
|
|
|
int bpp = pipe_config->pipe_bpp;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
|
|
|
|
connector->base.base.id,
|
|
|
|
drm_get_connector_name(&connector->base));
|
|
|
|
|
|
|
|
/* Don't use an invalid EDID bpc value */
|
|
|
|
if (connector->base.display_info.bpc &&
|
|
|
|
connector->base.display_info.bpc * 3 < bpp) {
|
|
|
|
DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
|
|
|
|
bpp, connector->base.display_info.bpc*3);
|
|
|
|
pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clamp bpp to 8 on screens without EDID 1.4 */
|
|
|
|
if (connector->base.display_info.bpc == 0 && bpp > 24) {
|
|
|
|
DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
|
|
|
|
bpp);
|
|
|
|
pipe_config->pipe_bpp = 24;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
static int
|
2013-06-02 19:26:23 +08:00
|
|
|
compute_baseline_pipe_bpp(struct intel_crtc *crtc,
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
struct intel_crtc_config *pipe_config)
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
{
|
2013-06-02 19:26:23 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct intel_connector *connector;
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
int bpp;
|
|
|
|
|
2013-03-28 23:38:08 +08:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
case DRM_FORMAT_C8:
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
bpp = 8*3; /* since we go through a colormap */
|
|
|
|
break;
|
2013-03-28 23:38:08 +08:00
|
|
|
case DRM_FORMAT_XRGB1555:
|
|
|
|
case DRM_FORMAT_ARGB1555:
|
|
|
|
/* checked in intel_framebuffer_init already */
|
|
|
|
if (WARN_ON(INTEL_INFO(dev)->gen > 3))
|
|
|
|
return -EINVAL;
|
|
|
|
case DRM_FORMAT_RGB565:
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
bpp = 6*3; /* min is 18bpp */
|
|
|
|
break;
|
2013-03-28 23:38:08 +08:00
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
/* checked in intel_framebuffer_init already */
|
|
|
|
if (WARN_ON(INTEL_INFO(dev)->gen < 4))
|
|
|
|
return -EINVAL;
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
bpp = 8*3;
|
|
|
|
break;
|
2013-03-28 23:38:08 +08:00
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
|
/* checked in intel_framebuffer_init already */
|
|
|
|
if (WARN_ON(INTEL_INFO(dev)->gen < 4))
|
2013-03-27 07:45:00 +08:00
|
|
|
return -EINVAL;
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
bpp = 10*3;
|
|
|
|
break;
|
2013-03-27 07:45:00 +08:00
|
|
|
/* TODO: gen4+ supports 16 bpc floating point, too. */
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
default:
|
|
|
|
DRM_DEBUG_KMS("unsupported depth\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe_config->pipe_bpp = bpp;
|
|
|
|
|
|
|
|
/* Clamp display bpp to EDID value */
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
2013-06-02 19:26:23 +08:00
|
|
|
base.head) {
|
|
|
|
if (connector->base.encoder &&
|
|
|
|
connector->base.encoder->crtc != crtc)
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
continue;
|
|
|
|
|
2013-06-02 19:26:23 +08:00
|
|
|
connected_sink_compute_bpp(connector, pipe_config);
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return bpp;
|
|
|
|
}
|
|
|
|
|
2013-05-28 18:05:54 +08:00
|
|
|
static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|
|
|
struct intel_crtc_config *pipe_config,
|
|
|
|
const char *context)
|
|
|
|
{
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id,
|
|
|
|
context, pipe_name(crtc->pipe));
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder));
|
|
|
|
DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
|
|
|
|
pipe_config->pipe_bpp, pipe_config->dither);
|
|
|
|
DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
|
|
|
|
pipe_config->has_pch_encoder,
|
|
|
|
pipe_config->fdi_lanes,
|
|
|
|
pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n,
|
|
|
|
pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n,
|
|
|
|
pipe_config->fdi_m_n.tu);
|
|
|
|
DRM_DEBUG_KMS("requested mode:\n");
|
|
|
|
drm_mode_debug_printmodeline(&pipe_config->requested_mode);
|
|
|
|
DRM_DEBUG_KMS("adjusted mode:\n");
|
|
|
|
drm_mode_debug_printmodeline(&pipe_config->adjusted_mode);
|
|
|
|
DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
|
|
|
|
pipe_config->gmch_pfit.control,
|
|
|
|
pipe_config->gmch_pfit.pgm_ratios,
|
|
|
|
pipe_config->gmch_pfit.lvds_border_bits);
|
|
|
|
DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
|
|
|
|
pipe_config->pch_pfit.pos,
|
|
|
|
pipe_config->pch_pfit.size);
|
2013-06-01 03:33:22 +08:00
|
|
|
DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
|
2013-05-28 18:05:54 +08:00
|
|
|
}
|
|
|
|
|
2013-03-27 07:44:50 +08:00
|
|
|
static struct intel_crtc_config *
|
|
|
|
intel_modeset_pipe_config(struct drm_crtc *crtc,
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
struct drm_framebuffer *fb,
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *mode)
|
2012-04-21 00:11:53 +08:00
|
|
|
{
|
2012-07-09 01:40:39 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct drm_encoder_helper_funcs *encoder_funcs;
|
|
|
|
struct intel_encoder *encoder;
|
2013-03-27 07:44:50 +08:00
|
|
|
struct intel_crtc_config *pipe_config;
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
int plane_bpp, ret = -EINVAL;
|
|
|
|
bool retry = true;
|
2012-04-21 00:11:53 +08:00
|
|
|
|
2013-03-27 07:44:50 +08:00
|
|
|
pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
|
|
|
|
if (!pipe_config)
|
2012-07-09 01:40:39 +08:00
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2013-03-27 07:44:50 +08:00
|
|
|
drm_mode_copy(&pipe_config->adjusted_mode, mode);
|
|
|
|
drm_mode_copy(&pipe_config->requested_mode, mode);
|
2013-05-22 06:50:22 +08:00
|
|
|
pipe_config->cpu_transcoder = to_intel_crtc(crtc)->pipe;
|
2013-03-27 07:44:50 +08:00
|
|
|
|
2013-06-02 19:26:23 +08:00
|
|
|
/* 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. */
|
|
|
|
plane_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
|
|
|
|
fb, pipe_config);
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
if (plane_bpp < 0)
|
|
|
|
goto fail;
|
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
encoder_retry:
|
2012-07-09 01:40:39 +08:00
|
|
|
/* 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.
|
2010-12-03 23:37:31 +08:00
|
|
|
*/
|
2012-07-09 01:40:39 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-09 01:40:39 +08:00
|
|
|
if (&encoder->new_crtc->base != crtc)
|
|
|
|
continue;
|
2013-03-27 07:44:52 +08:00
|
|
|
|
|
|
|
if (encoder->compute_config) {
|
|
|
|
if (!(encoder->compute_config(encoder, pipe_config))) {
|
|
|
|
DRM_DEBUG_KMS("Encoder config failure\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-07-09 01:40:39 +08:00
|
|
|
encoder_funcs = encoder->base.helper_private;
|
2013-03-27 07:44:50 +08:00
|
|
|
if (!(encoder_funcs->mode_fixup(&encoder->base,
|
|
|
|
&pipe_config->requested_mode,
|
|
|
|
&pipe_config->adjusted_mode))) {
|
2012-07-09 01:40:39 +08:00
|
|
|
DRM_DEBUG_KMS("Encoder fixup failed\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
2012-04-21 00:11:53 +08:00
|
|
|
}
|
2010-12-03 23:37:31 +08:00
|
|
|
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
ret = intel_crtc_compute_config(crtc, pipe_config);
|
|
|
|
if (ret < 0) {
|
2012-07-09 01:40:39 +08:00
|
|
|
DRM_DEBUG_KMS("CRTC fixup failed\n");
|
|
|
|
goto fail;
|
2012-04-21 00:11:53 +08:00
|
|
|
}
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
|
|
|
|
if (ret == RETRY) {
|
|
|
|
if (WARN(!retry, "loop in pipe configuration computation\n")) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("CRTC bw constrained, retrying\n");
|
|
|
|
retry = false;
|
|
|
|
goto encoder_retry;
|
|
|
|
}
|
|
|
|
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
pipe_config->dither = pipe_config->pipe_bpp != plane_bpp;
|
|
|
|
DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
|
|
|
|
plane_bpp, pipe_config->pipe_bpp, pipe_config->dither);
|
|
|
|
|
2013-03-27 07:44:50 +08:00
|
|
|
return pipe_config;
|
2012-07-09 01:40:39 +08:00
|
|
|
fail:
|
2013-03-27 07:44:50 +08:00
|
|
|
kfree(pipe_config);
|
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw
VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit
into this, among them the default 1080p mode.
The solution is to dither down the pipe a bit so that everything fits,
which this patch implements.
But ports compute their state under the assumption that the bpp they
pick will be the one selected, e.g. the display port bw computations
won't work otherwise. Now we could adjust our code to again up-dither
to the computed DP link parameters, but that's pointless.
So instead when the pipe needs to adjust parameters we need to retry
the pipe_config computation at the encoder stage. Furthermore we need
to inform encoders that they should not increase bandwidth
requirements if possible. This is required for the hdmi code, which
prefers the pipe to up-dither to either of the two possible hdmi bpc
values.
LVDS has a similar requirement, although that's probably only
theoretical in nature: It's unlikely that we'll ever see an 8bpc
high-res lvds panel (which is required to hit the 2 fdi lane limit).
eDP is the only thing which could increase the pipe_bpp setting again,
even when in the retry-loop. This could hit the WARN. Two reasons for
not bothering:
- On many eDP panels we'll get a black screen if the bpp settings
don't match vbt. So failing the modeset is the right thing to do.
But since that also means it's the only way to light up the panel,
it should work. So we shouldn't be able to hit this WARN.
- There are still opens around the eDP panel handling, and maybe we
need additional tricks. Before that happens it's imo no use trying
to be too clever.
Worst case we just need to kill that WARN or maybe fail the compute
config stage if the eDP connector can't get the bpp setting it wants.
And since this can only happen with an fdi link in between and so for
pch eDP panels it's rather unlikely to blow up, if ever.
v2: Rebased on top of a bikeshed from Paulo.
v3: Improve commit message around eDP handling with the stuff
things with Imre.
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-21 07:00:16 +08:00
|
|
|
return ERR_PTR(ret);
|
2012-04-21 00:11:53 +08:00
|
|
|
}
|
2010-12-03 23:37:31 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
/* 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
|
|
|
|
intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
|
|
|
|
unsigned *prepare_pipes, unsigned *disable_pipes)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
struct intel_crtc *intel_crtc;
|
2012-07-09 03:14:38 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
|
|
|
struct drm_crtc *tmp_crtc;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
*disable_pipes = *modeset_pipes = *prepare_pipes = 0;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
/* 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. */
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->base.encoder == &connector->new_encoder->base)
|
|
|
|
continue;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
if (connector->base.encoder) {
|
|
|
|
tmp_crtc = connector->base.encoder->crtc;
|
|
|
|
|
|
|
|
*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connector->new_encoder)
|
|
|
|
*prepare_pipes |=
|
|
|
|
1 << connector->new_encoder->new_crtc->pipe;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
if (encoder->base.crtc == &encoder->new_crtc->base)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (encoder->base.crtc) {
|
|
|
|
tmp_crtc = encoder->base.crtc;
|
|
|
|
|
|
|
|
*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (encoder->new_crtc)
|
|
|
|
*prepare_pipes |= 1 << encoder->new_crtc->pipe;
|
2009-09-11 06:28:06 +08:00
|
|
|
}
|
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
/* Check for any pipes that will be fully disabled ... */
|
|
|
|
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
|
|
|
|
base.head) {
|
|
|
|
bool used = false;
|
2009-12-03 05:42:53 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
/* Don't try to disable disabled crtcs. */
|
|
|
|
if (!intel_crtc->base.enabled)
|
|
|
|
continue;
|
2010-09-11 01:47:20 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
if (encoder->new_crtc == intel_crtc)
|
|
|
|
used = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!used)
|
|
|
|
*disable_pipes |= 1 << intel_crtc->pipe;
|
2010-09-11 01:47:20 +08:00
|
|
|
}
|
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
|
|
|
|
/* set_mode is also used to update properties on life display pipes. */
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
|
|
|
if (crtc->enabled)
|
|
|
|
*prepare_pipes |= 1 << intel_crtc->pipe;
|
|
|
|
|
2013-04-13 00:48:43 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2012-07-09 03:14:38 +08:00
|
|
|
if (*prepare_pipes)
|
|
|
|
*modeset_pipes = *prepare_pipes;
|
|
|
|
|
|
|
|
/* ... and mask these out. */
|
|
|
|
*modeset_pipes &= ~(*disable_pipes);
|
|
|
|
*prepare_pipes &= ~(*disable_pipes);
|
2013-04-13 00:48:43 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
*modeset_pipes &= 1 << intel_crtc->pipe;
|
|
|
|
*prepare_pipes &= 1 << intel_crtc->pipe;
|
2013-04-12 01:49:07 +08:00
|
|
|
|
|
|
|
DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
|
|
|
|
*modeset_pipes, *prepare_pipes, *disable_pipes);
|
2010-12-03 23:37:31 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
static bool intel_crtc_in_use(struct drm_crtc *crtc)
|
2011-04-13 01:06:51 +08:00
|
|
|
{
|
2012-07-10 16:42:52 +08:00
|
|
|
struct drm_encoder *encoder;
|
2011-04-13 01:06:51 +08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
|
|
|
|
if (encoder->crtc == crtc)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
|
|
|
|
{
|
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
struct drm_connector *connector;
|
|
|
|
|
|
|
|
list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
if (!intel_encoder->base.crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
|
|
|
|
|
|
|
|
if (prepare_pipes & (1 << intel_crtc->pipe))
|
|
|
|
intel_encoder->connectors_active = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
intel_modeset_commit_output_state(dev);
|
|
|
|
|
|
|
|
/* Update computed state. */
|
|
|
|
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
|
|
|
|
base.head) {
|
|
|
|
intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
|
|
if (!connector->encoder || !connector->encoder->crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intel_crtc = to_intel_crtc(connector->encoder->crtc);
|
|
|
|
|
|
|
|
if (prepare_pipes & (1 << intel_crtc->pipe)) {
|
2012-09-07 04:08:35 +08:00
|
|
|
struct drm_property *dpms_property =
|
|
|
|
dev->mode_config.dpms_property;
|
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
connector->dpms = DRM_MODE_DPMS_ON;
|
2012-10-12 09:36:04 +08:00
|
|
|
drm_object_property_set_value(&connector->base,
|
2012-09-07 04:08:35 +08:00
|
|
|
dpms_property,
|
|
|
|
DRM_MODE_DPMS_ON);
|
2012-07-10 16:42:52 +08:00
|
|
|
|
|
|
|
intel_encoder = to_intel_encoder(connector->encoder);
|
|
|
|
intel_encoder->connectors_active = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-07-09 04:08:04 +08:00
|
|
|
#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
|
|
|
|
list_for_each_entry((intel_crtc), \
|
|
|
|
&(dev)->mode_config.crtc_list, \
|
|
|
|
base.head) \
|
2013-04-19 17:25:33 +08:00
|
|
|
if (mask & (1 <<(intel_crtc)->pipe))
|
2012-07-09 04:08:04 +08:00
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
static bool
|
2013-05-08 05:34:16 +08:00
|
|
|
intel_pipe_config_compare(struct drm_device *dev,
|
|
|
|
struct intel_crtc_config *current_config,
|
2013-03-28 17:42:00 +08:00
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
|
{
|
2013-04-19 17:25:34 +08:00
|
|
|
#define PIPE_CONF_CHECK_I(name) \
|
|
|
|
if (current_config->name != pipe_config->name) { \
|
|
|
|
DRM_ERROR("mismatch in " #name " " \
|
|
|
|
"(expected %i, found %i)\n", \
|
|
|
|
current_config->name, \
|
|
|
|
pipe_config->name); \
|
|
|
|
return false; \
|
2013-03-28 17:42:01 +08:00
|
|
|
}
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
#define PIPE_CONF_CHECK_FLAGS(name, mask) \
|
|
|
|
if ((current_config->name ^ pipe_config->name) & (mask)) { \
|
|
|
|
DRM_ERROR("mismatch in " #name " " \
|
|
|
|
"(expected %i, found %i)\n", \
|
|
|
|
current_config->name & (mask), \
|
|
|
|
pipe_config->name & (mask)); \
|
|
|
|
return false; \
|
|
|
|
}
|
|
|
|
|
2013-05-22 06:50:22 +08:00
|
|
|
PIPE_CONF_CHECK_I(cpu_transcoder);
|
|
|
|
|
2013-04-19 17:25:34 +08:00
|
|
|
PIPE_CONF_CHECK_I(has_pch_encoder);
|
|
|
|
PIPE_CONF_CHECK_I(fdi_lanes);
|
2013-04-04 19:28:53 +08:00
|
|
|
PIPE_CONF_CHECK_I(fdi_m_n.gmch_m);
|
|
|
|
PIPE_CONF_CHECK_I(fdi_m_n.gmch_n);
|
|
|
|
PIPE_CONF_CHECK_I(fdi_m_n.link_m);
|
|
|
|
PIPE_CONF_CHECK_I(fdi_m_n.link_n);
|
|
|
|
PIPE_CONF_CHECK_I(fdi_m_n.tu);
|
2013-04-19 17:25:34 +08:00
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_end);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_start);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hsync_end);
|
|
|
|
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vdisplay);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vtotal);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_start);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vblank_end);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start);
|
|
|
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end);
|
|
|
|
|
|
|
|
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
|
|
|
DRM_MODE_FLAG_INTERLACE);
|
|
|
|
|
2013-05-15 08:08:26 +08:00
|
|
|
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
|
|
|
DRM_MODE_FLAG_PHSYNC);
|
|
|
|
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
|
|
|
DRM_MODE_FLAG_NHSYNC);
|
|
|
|
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
|
|
|
DRM_MODE_FLAG_PVSYNC);
|
|
|
|
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
|
|
|
DRM_MODE_FLAG_NVSYNC);
|
|
|
|
|
2013-04-30 03:56:12 +08:00
|
|
|
PIPE_CONF_CHECK_I(requested_mode.hdisplay);
|
|
|
|
PIPE_CONF_CHECK_I(requested_mode.vdisplay);
|
|
|
|
|
2013-05-08 05:34:16 +08:00
|
|
|
PIPE_CONF_CHECK_I(gmch_pfit.control);
|
|
|
|
/* pfit ratios are autocomputed by the hw on gen4+ */
|
|
|
|
if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
|
|
|
|
PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
|
|
|
|
PIPE_CONF_CHECK_I(pch_pfit.pos);
|
|
|
|
PIPE_CONF_CHECK_I(pch_pfit.size);
|
|
|
|
|
2013-06-01 03:33:22 +08:00
|
|
|
PIPE_CONF_CHECK_I(ips_enabled);
|
|
|
|
|
2013-04-19 17:25:34 +08:00
|
|
|
#undef PIPE_CONF_CHECK_I
|
2013-04-30 03:56:12 +08:00
|
|
|
#undef PIPE_CONF_CHECK_FLAGS
|
2013-04-30 01:33:42 +08:00
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-31 23:37:33 +08:00
|
|
|
void
|
2012-07-10 15:50:11 +08:00
|
|
|
intel_modeset_check_state(struct drm_device *dev)
|
|
|
|
{
|
2013-03-28 17:42:00 +08:00
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
2012-07-10 15:50:11 +08:00
|
|
|
struct intel_crtc *crtc;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
2013-03-28 17:42:00 +08:00
|
|
|
struct intel_crtc_config pipe_config;
|
2012-07-10 15:50:11 +08:00
|
|
|
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
/* This also checks the encoder/connector hw state with the
|
|
|
|
* ->get_hw_state callbacks. */
|
|
|
|
intel_connector_check_state(connector);
|
|
|
|
|
|
|
|
WARN(&connector->new_encoder->base != connector->base.encoder,
|
|
|
|
"connector's staged encoder doesn't match current encoder\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
bool enabled = false;
|
|
|
|
bool active = false;
|
|
|
|
enum pipe pipe, tracked_pipe;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
|
|
|
|
encoder->base.base.id,
|
|
|
|
drm_get_encoder_name(&encoder->base));
|
|
|
|
|
|
|
|
WARN(&encoder->new_crtc->base != encoder->base.crtc,
|
|
|
|
"encoder's stage crtc doesn't match current crtc\n");
|
|
|
|
WARN(encoder->connectors_active && !encoder->base.crtc,
|
|
|
|
"encoder's active_connectors set, but no crtc\n");
|
|
|
|
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->base.encoder != &encoder->base)
|
|
|
|
continue;
|
|
|
|
enabled = true;
|
|
|
|
if (connector->base.dpms != DRM_MODE_DPMS_OFF)
|
|
|
|
active = true;
|
|
|
|
}
|
|
|
|
WARN(!!encoder->base.crtc != enabled,
|
|
|
|
"encoder's enabled state mismatch "
|
|
|
|
"(expected %i, found %i)\n",
|
|
|
|
!!encoder->base.crtc, enabled);
|
|
|
|
WARN(active && !encoder->base.crtc,
|
|
|
|
"active encoder with no crtc\n");
|
|
|
|
|
|
|
|
WARN(encoder->connectors_active != active,
|
|
|
|
"encoder's computed active state doesn't match tracked active state "
|
|
|
|
"(expected %i, found %i)\n", active, encoder->connectors_active);
|
|
|
|
|
|
|
|
active = encoder->get_hw_state(encoder, &pipe);
|
|
|
|
WARN(active != encoder->connectors_active,
|
|
|
|
"encoder's hw state doesn't match sw tracking "
|
|
|
|
"(expected %i, found %i)\n",
|
|
|
|
encoder->connectors_active, active);
|
|
|
|
|
|
|
|
if (!encoder->base.crtc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe;
|
|
|
|
WARN(active && pipe != tracked_pipe,
|
|
|
|
"active encoder's pipe doesn't match"
|
|
|
|
"(expected %i, found %i)\n",
|
|
|
|
tracked_pipe, pipe);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
|
|
|
|
base.head) {
|
|
|
|
bool enabled = false;
|
|
|
|
bool active = false;
|
|
|
|
|
2013-05-15 08:08:26 +08:00
|
|
|
memset(&pipe_config, 0, sizeof(pipe_config));
|
|
|
|
|
2012-07-10 15:50:11 +08:00
|
|
|
DRM_DEBUG_KMS("[CRTC:%d]\n",
|
|
|
|
crtc->base.base.id);
|
|
|
|
|
|
|
|
WARN(crtc->active && !crtc->base.enabled,
|
|
|
|
"active crtc, but not enabled in sw tracking\n");
|
|
|
|
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
if (encoder->base.crtc != &crtc->base)
|
|
|
|
continue;
|
|
|
|
enabled = true;
|
|
|
|
if (encoder->connectors_active)
|
|
|
|
active = true;
|
2013-05-15 08:08:26 +08:00
|
|
|
if (encoder->get_config)
|
|
|
|
encoder->get_config(encoder, &pipe_config);
|
2012-07-10 15:50:11 +08:00
|
|
|
}
|
|
|
|
WARN(active != crtc->active,
|
|
|
|
"crtc's computed active state doesn't match tracked active state "
|
|
|
|
"(expected %i, found %i)\n", active, crtc->active);
|
|
|
|
WARN(enabled != crtc->base.enabled,
|
|
|
|
"crtc's computed enabled state doesn't match tracked enabled state "
|
|
|
|
"(expected %i, found %i)\n", enabled, crtc->base.enabled);
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
active = dev_priv->display.get_pipe_config(crtc,
|
|
|
|
&pipe_config);
|
|
|
|
WARN(crtc->active != active,
|
|
|
|
"crtc active state doesn't match with hw state "
|
|
|
|
"(expected %i, found %i)\n", crtc->active, active);
|
|
|
|
|
2013-05-28 18:05:54 +08:00
|
|
|
if (active &&
|
|
|
|
!intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) {
|
|
|
|
WARN(1, "pipe state doesn't match!\n");
|
|
|
|
intel_dump_pipe_config(crtc, &pipe_config,
|
|
|
|
"[hw state]");
|
|
|
|
intel_dump_pipe_config(crtc, &crtc->config,
|
|
|
|
"[sw state]");
|
|
|
|
}
|
2012-07-10 15:50:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-12 02:22:50 +08:00
|
|
|
static int __intel_set_mode(struct drm_crtc *crtc,
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
int x, int y, struct drm_framebuffer *fb)
|
2012-07-02 15:56:42 +08:00
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2012-07-02 17:18:29 +08:00
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
2013-03-27 07:44:50 +08:00
|
|
|
struct drm_display_mode *saved_mode, *saved_hwmode;
|
|
|
|
struct intel_crtc_config *pipe_config = NULL;
|
2012-07-09 04:08:04 +08:00
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
unsigned disable_pipes, prepare_pipes, modeset_pipes;
|
2012-12-20 00:08:43 +08:00
|
|
|
int ret = 0;
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-12-07 22:54:26 +08:00
|
|
|
saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL);
|
2012-12-20 00:08:43 +08:00
|
|
|
if (!saved_mode)
|
|
|
|
return -ENOMEM;
|
2012-12-07 22:54:26 +08:00
|
|
|
saved_hwmode = saved_mode + 1;
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-07-09 03:14:38 +08:00
|
|
|
intel_modeset_affected_pipes(crtc, &modeset_pipes,
|
2012-07-09 04:08:04 +08:00
|
|
|
&prepare_pipes, &disable_pipes);
|
|
|
|
|
2012-12-07 22:54:26 +08:00
|
|
|
*saved_hwmode = crtc->hwmode;
|
|
|
|
*saved_mode = crtc->mode;
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-07-09 04:08:04 +08:00
|
|
|
/* 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) {
|
drm/i915: precompute pipe bpp before touching the hw
The procedure has now 3 steps:
1. Compute the bpp that the plane will output, this is done in
pipe_config_set_bpp and stored into pipe_config->pipe_bpp. Also,
this function clamps the pipe_bpp to whatever limit the EDID of any
connected output specifies.
2. Adjust the pipe_bpp in the encoder and crtc functions, according to
whatever constraints there are.
3. Decide whether to use dither by comparing the stored plane bpp with
computed pipe_bpp.
There are a few slight functional changes in this patch:
- LVDS connector are now also going through the EDID clamping. But in
a 2nd change we now unconditionally force the lvds bpc value - this
shouldn't matter in reality when the panel setup is consistent, but
better safe than sorry.
- HDMI now forces the pipe_bpp to the selected value - I think that's
what we actually want, since otherwise at least the pixelclock
computations are wrong (I'm not sure whether the port would accept
e.g. 10 bpc when in 12bpc mode). Contrary to the old code, we pick
the next higher bpc value, since otherwise there's no way to make
use of the 12 bpc mode (since the next patch will remove the 12bpc
plane format, it doesn't exist).
Both of these changes are due to the removal of the
pipe_bpp = min(display_bpp, plane_bpp);
statement.
Another slight change is the reworking of the dp bpc code:
- For the mode_valid callback it's sufficient to only check whether
the mode would fit at the lowest bpc.
- The bandwidth computation code is a bit restructured: It now walks
all available bpp values in an outer loop and the codeblock that
computes derived values (once a good configuration is found) has been
moved out of the for loop maze. This is prep work to allow us to
successively fall back on bpc values, and also correctly support bpc
values != 8 or 6.
v2: Rebased on top of Paulo Zanoni's little refactoring to use more
drm dp helper functions.
v3: Rebased on top of Jani's eDP bpp fix and Ville's limited color
range work.
v4: Remove the INTEL_MODE_DP_FORCE_6BPC #define, no longer needed.
v5: Remove intel_crtc->bpp, too, and fix up the 12bpc check in the
hdmi code. Also fixup the bpp check in intel_dp.c, it'll get reworked
in a later patch though again.
v6: Fix spelling in a comment.
v7: Debug output improvements for the bpp computation.
v8: Fixup 6bpc lvds check - dual-link and 8bpc mode are different
things!
v9: Reinstate the fix to properly ignore the firmware edp bpp ... this
was lost in a rebase.
v10: Both g4x and vlv lack 12bpc pipes, so don't enforce that we have
that. Still unsure whether this is the way to go, but at least 6bpc
for a 8bpc hdmi output seems to work.
v11: And g4x/vlv also lack 12bpc hdmi support, so only support high
depth on DP. Adjust the code.
v12: Rebased.
v13: Split out the introduction of pipe_config->dither|pipe_bpp, as
requested from Jesse Barnes.
v14: Split out the special 6BPC handling for DP, as requested by Jesse
Barnes.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-27 07:44:58 +08:00
|
|
|
pipe_config = intel_modeset_pipe_config(crtc, fb, mode);
|
2013-03-27 07:44:50 +08:00
|
|
|
if (IS_ERR(pipe_config)) {
|
|
|
|
ret = PTR_ERR(pipe_config);
|
|
|
|
pipe_config = NULL;
|
|
|
|
|
2012-12-07 22:54:26 +08:00
|
|
|
goto out;
|
2012-07-09 04:08:04 +08:00
|
|
|
}
|
2013-05-28 18:05:54 +08:00
|
|
|
intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
|
|
|
|
"[modeset]");
|
2012-07-09 04:08:04 +08:00
|
|
|
}
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2013-03-27 07:44:51 +08:00
|
|
|
for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
|
|
|
|
intel_crtc_disable(&intel_crtc->base);
|
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
|
|
|
|
if (intel_crtc->base.enabled)
|
|
|
|
dev_priv->display.crtc_disable(&intel_crtc->base);
|
|
|
|
}
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-09-11 03:58:30 +08:00
|
|
|
/* 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.
|
2011-04-13 01:06:51 +08:00
|
|
|
*/
|
2013-03-27 07:44:50 +08:00
|
|
|
if (modeset_pipes) {
|
2012-07-09 04:08:04 +08:00
|
|
|
crtc->mode = *mode;
|
2013-03-27 07:44:50 +08:00
|
|
|
/* mode_set/enable/disable functions rely on a correct pipe
|
|
|
|
* config. */
|
|
|
|
to_intel_crtc(crtc)->config = *pipe_config;
|
|
|
|
}
|
2012-07-09 01:40:39 +08:00
|
|
|
|
2012-07-10 16:42:52 +08:00
|
|
|
/* Only after disabling all output pipelines that will be changed can we
|
|
|
|
* update the the output configuration. */
|
|
|
|
intel_modeset_update_state(dev, prepare_pipes);
|
2011-04-13 01:06:51 +08:00
|
|
|
|
2012-10-26 16:58:18 +08:00
|
|
|
if (dev_priv->display.modeset_global_resources)
|
|
|
|
dev_priv->display.modeset_global_resources(dev);
|
|
|
|
|
2012-07-02 15:56:42 +08:00
|
|
|
/* Set up the DPLL and any encoders state that needs to adjust or depend
|
|
|
|
* on the DPLL.
|
2011-04-13 01:06:51 +08:00
|
|
|
*/
|
2012-07-09 04:08:04 +08:00
|
|
|
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
|
2012-12-20 00:08:43 +08:00
|
|
|
ret = intel_crtc_mode_set(&intel_crtc->base,
|
|
|
|
x, y, fb);
|
|
|
|
if (ret)
|
|
|
|
goto done;
|
2012-07-02 15:56:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
|
2012-07-09 04:08:04 +08:00
|
|
|
for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
|
|
|
|
dev_priv->display.crtc_enable(&intel_crtc->base);
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-07-09 04:08:04 +08:00
|
|
|
if (modeset_pipes) {
|
|
|
|
/* Store real post-adjustment hardware mode. */
|
2013-03-27 07:44:50 +08:00
|
|
|
crtc->hwmode = pipe_config->adjusted_mode;
|
2012-07-02 15:56:42 +08:00
|
|
|
|
2012-07-09 04:08:04 +08:00
|
|
|
/* Calculate and store various constants which
|
|
|
|
* are later needed by vblank and swap-completion
|
|
|
|
* timestamping. They are derived from true hwmode.
|
|
|
|
*/
|
|
|
|
drm_calc_timestamping_constants(crtc);
|
|
|
|
}
|
2012-07-02 15:56:42 +08:00
|
|
|
|
|
|
|
/* FIXME: add subpixel order */
|
|
|
|
done:
|
2012-12-20 00:08:43 +08:00
|
|
|
if (ret && crtc->enabled) {
|
2012-12-07 22:54:26 +08:00
|
|
|
crtc->hwmode = *saved_hwmode;
|
|
|
|
crtc->mode = *saved_mode;
|
2012-07-02 15:56:42 +08:00
|
|
|
}
|
|
|
|
|
2012-12-07 22:54:26 +08:00
|
|
|
out:
|
2013-03-27 07:44:50 +08:00
|
|
|
kfree(pipe_config);
|
2012-12-07 22:54:26 +08:00
|
|
|
kfree(saved_mode);
|
2012-07-02 15:56:42 +08:00
|
|
|
return ret;
|
2011-04-13 01:06:51 +08:00
|
|
|
}
|
|
|
|
|
2013-04-12 02:22:50 +08:00
|
|
|
int intel_set_mode(struct drm_crtc *crtc,
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
int x, int y, struct drm_framebuffer *fb)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = __intel_set_mode(crtc, mode, x, y, fb);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
intel_modeset_check_state(crtc->dev);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-12-20 00:08:43 +08:00
|
|
|
void intel_crtc_restore_mode(struct drm_crtc *crtc)
|
|
|
|
{
|
|
|
|
intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
|
|
|
|
}
|
|
|
|
|
2012-07-09 04:08:04 +08:00
|
|
|
#undef for_each_intel_crtc_masked
|
|
|
|
|
2012-07-05 04:16:09 +08:00
|
|
|
static void intel_set_config_free(struct intel_set_config *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
return;
|
|
|
|
|
2012-07-05 22:20:48 +08:00
|
|
|
kfree(config->save_connector_encoders);
|
|
|
|
kfree(config->save_encoder_crtcs);
|
2012-07-05 04:16:09 +08:00
|
|
|
kfree(config);
|
|
|
|
}
|
|
|
|
|
2012-07-05 04:24:08 +08:00
|
|
|
static int intel_set_config_save_state(struct drm_device *dev,
|
|
|
|
struct intel_set_config *config)
|
|
|
|
{
|
|
|
|
struct drm_encoder *encoder;
|
|
|
|
struct drm_connector *connector;
|
|
|
|
int count;
|
|
|
|
|
2012-07-05 22:20:48 +08:00
|
|
|
config->save_encoder_crtcs =
|
|
|
|
kcalloc(dev->mode_config.num_encoder,
|
|
|
|
sizeof(struct drm_crtc *), GFP_KERNEL);
|
|
|
|
if (!config->save_encoder_crtcs)
|
2012-07-05 04:24:08 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2012-07-05 22:20:48 +08:00
|
|
|
config->save_connector_encoders =
|
|
|
|
kcalloc(dev->mode_config.num_connector,
|
|
|
|
sizeof(struct drm_encoder *), GFP_KERNEL);
|
|
|
|
if (!config->save_connector_encoders)
|
2012-07-05 04:24:08 +08:00
|
|
|
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;
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
2012-07-05 22:20:48 +08:00
|
|
|
config->save_encoder_crtcs[count++] = encoder->crtc;
|
2012-07-05 04:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
2012-07-05 22:20:48 +08:00
|
|
|
config->save_connector_encoders[count++] = connector->encoder;
|
2012-07-05 04:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void intel_set_config_restore_state(struct drm_device *dev,
|
|
|
|
struct intel_set_config *config)
|
|
|
|
{
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
2012-07-05 04:24:08 +08:00
|
|
|
int count;
|
|
|
|
|
|
|
|
count = 0;
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
|
|
|
|
encoder->new_crtc =
|
|
|
|
to_intel_crtc(config->save_encoder_crtcs[count++]);
|
2012-07-05 04:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
|
|
|
|
connector->new_encoder =
|
|
|
|
to_intel_encoder(config->save_connector_encoders[count++]);
|
2012-07-05 04:24:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-05 04:41:29 +08:00
|
|
|
static void
|
|
|
|
intel_set_config_compute_mode_changes(struct drm_mode_set *set,
|
|
|
|
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 (set->crtc->fb != set->fb) {
|
|
|
|
/* If we have no fb then treat it as a full mode set */
|
|
|
|
if (set->crtc->fb == NULL) {
|
|
|
|
DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
|
|
|
|
config->mode_changed = true;
|
|
|
|
} else if (set->fb == NULL) {
|
|
|
|
config->mode_changed = true;
|
2013-03-28 23:01:35 +08:00
|
|
|
} else if (set->fb->pixel_format !=
|
|
|
|
set->crtc->fb->pixel_format) {
|
2012-07-05 04:41:29 +08:00
|
|
|
config->mode_changed = true;
|
|
|
|
} else
|
|
|
|
config->fb_changed = true;
|
|
|
|
}
|
|
|
|
|
2012-07-11 00:11:08 +08:00
|
|
|
if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
|
2012-07-05 04:41:29 +08:00
|
|
|
config->fb_changed = true;
|
|
|
|
|
|
|
|
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
|
|
|
|
DRM_DEBUG_KMS("modes are different, full mode set\n");
|
|
|
|
drm_mode_debug_printmodeline(&set->crtc->mode);
|
|
|
|
drm_mode_debug_printmodeline(set->mode);
|
|
|
|
config->mode_changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-05 04:42:15 +08:00
|
|
|
static int
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
intel_modeset_stage_output_state(struct drm_device *dev,
|
|
|
|
struct drm_mode_set *set,
|
|
|
|
struct intel_set_config *config)
|
2012-07-02 15:35:43 +08:00
|
|
|
{
|
2012-07-05 04:24:08 +08:00
|
|
|
struct drm_crtc *new_crtc;
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
struct intel_connector *connector;
|
|
|
|
struct intel_encoder *encoder;
|
2012-07-05 04:42:15 +08:00
|
|
|
int count, ro;
|
2012-07-02 15:35:43 +08:00
|
|
|
|
2013-02-13 21:29:23 +08:00
|
|
|
/* The upper layers ensure that we either disable a crtc or have a list
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
* of connectors. For paranoia, double-check this. */
|
|
|
|
WARN_ON(!set->fb && (set->num_connectors != 0));
|
|
|
|
WARN_ON(set->fb && (set->num_connectors == 0));
|
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
count = 0;
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
/* Otherwise traverse passed in connector list and get encoders
|
|
|
|
* for them. */
|
2012-07-02 15:35:43 +08:00
|
|
|
for (ro = 0; ro < set->num_connectors; ro++) {
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
if (set->connectors[ro] == &connector->base) {
|
|
|
|
connector->new_encoder = connector->encoder;
|
2012-07-02 15:35:43 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/* 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. */
|
|
|
|
if ((!set->fb || ro == set->num_connectors) &&
|
|
|
|
connector->base.encoder &&
|
|
|
|
connector->base.encoder->crtc == set->crtc) {
|
|
|
|
connector->new_encoder = NULL;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
|
|
|
|
connector->base.base.id,
|
|
|
|
drm_get_connector_name(&connector->base));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (&connector->new_encoder->base != connector->base.encoder) {
|
2012-07-02 15:35:43 +08:00
|
|
|
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
|
2012-07-05 04:41:29 +08:00
|
|
|
config->mode_changed = true;
|
2012-07-02 15:35:43 +08:00
|
|
|
}
|
|
|
|
}
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/* connector->new_encoder is now updated for all connectors. */
|
2012-07-02 15:35:43 +08:00
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/* Update crtc of enabled connectors. */
|
2012-07-02 15:35:43 +08:00
|
|
|
count = 0;
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (!connector->new_encoder)
|
2012-07-02 15:35:43 +08:00
|
|
|
continue;
|
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
new_crtc = connector->new_encoder->base.crtc;
|
2012-07-02 15:35:43 +08:00
|
|
|
|
|
|
|
for (ro = 0; ro < set->num_connectors; ro++) {
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
if (set->connectors[ro] == &connector->base)
|
2012-07-02 15:35:43 +08:00
|
|
|
new_crtc = set->crtc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure the new CRTC will work with the encoder */
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
|
|
|
|
new_crtc)) {
|
2012-07-05 04:41:29 +08:00
|
|
|
return -EINVAL;
|
2012-07-02 15:35:43 +08:00
|
|
|
}
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
connector->encoder->new_crtc = to_intel_crtc(new_crtc);
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
|
|
|
|
connector->base.base.id,
|
|
|
|
drm_get_connector_name(&connector->base),
|
|
|
|
new_crtc->base.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for any encoders that needs to be disabled. */
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
list_for_each_entry(connector,
|
|
|
|
&dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->new_encoder == encoder) {
|
|
|
|
WARN_ON(!connector->new_encoder->new_crtc);
|
|
|
|
|
|
|
|
goto next_encoder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
encoder->new_crtc = NULL;
|
|
|
|
next_encoder:
|
|
|
|
/* Only now check for crtc changes so we don't miss encoders
|
|
|
|
* that will be disabled. */
|
|
|
|
if (&encoder->new_crtc->base != encoder->base.crtc) {
|
2012-07-02 15:35:43 +08:00
|
|
|
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
|
2012-07-05 04:41:29 +08:00
|
|
|
config->mode_changed = true;
|
2012-07-02 15:35:43 +08:00
|
|
|
}
|
|
|
|
}
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
/* Now we've also updated encoder->new_crtc for all encoders. */
|
2012-07-02 15:35:43 +08:00
|
|
|
|
2012-07-05 04:42:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_crtc_set_config(struct drm_mode_set *set)
|
|
|
|
{
|
|
|
|
struct drm_device *dev;
|
|
|
|
struct drm_mode_set save_set;
|
|
|
|
struct intel_set_config *config;
|
|
|
|
int ret;
|
|
|
|
|
2012-07-05 22:09:09 +08:00
|
|
|
BUG_ON(!set);
|
|
|
|
BUG_ON(!set->crtc);
|
|
|
|
BUG_ON(!set->crtc->helper_private);
|
2012-07-05 04:42:15 +08:00
|
|
|
|
2013-01-21 17:52:17 +08:00
|
|
|
/* Enforce sane interface api - has been abused by the fb helper. */
|
|
|
|
BUG_ON(!set->mode && set->fb);
|
|
|
|
BUG_ON(set->fb && set->num_connectors == 0);
|
2012-07-10 23:53:42 +08:00
|
|
|
|
2012-07-05 04:42:15 +08:00
|
|
|
if (set->fb) {
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
|
|
|
|
set->crtc->base.id, set->fb->base.id,
|
|
|
|
(int)set->num_connectors, set->x, set->y);
|
|
|
|
} else {
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
dev = set->crtc->dev;
|
|
|
|
|
|
|
|
ret = -ENOMEM;
|
|
|
|
config = kzalloc(sizeof(*config), GFP_KERNEL);
|
|
|
|
if (!config)
|
|
|
|
goto out_config;
|
|
|
|
|
|
|
|
ret = intel_set_config_save_state(dev, config);
|
|
|
|
if (ret)
|
|
|
|
goto out_config;
|
|
|
|
|
|
|
|
save_set.crtc = set->crtc;
|
|
|
|
save_set.mode = &set->crtc->mode;
|
|
|
|
save_set.x = set->crtc->x;
|
|
|
|
save_set.y = set->crtc->y;
|
|
|
|
save_set.fb = set->crtc->fb;
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
intel_set_config_compute_mode_changes(set, config);
|
|
|
|
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
ret = intel_modeset_stage_output_state(dev, set, config);
|
2012-07-05 04:42:15 +08:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2012-07-05 04:41:29 +08:00
|
|
|
if (config->mode_changed) {
|
2012-12-20 00:08:43 +08:00
|
|
|
ret = intel_set_mode(set->crtc, set->mode,
|
|
|
|
set->x, set->y, set->fb);
|
|
|
|
if (ret) {
|
|
|
|
DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
|
|
|
|
set->crtc->base.id, ret);
|
2012-07-06 05:36:17 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2012-07-05 04:41:29 +08:00
|
|
|
} else if (config->fb_changed) {
|
2013-02-19 01:08:48 +08:00
|
|
|
intel_crtc_wait_for_pending_flips(set->crtc);
|
|
|
|
|
2012-07-02 15:47:37 +08:00
|
|
|
ret = intel_pipe_set_base(set->crtc,
|
drm/i915: push crtc->fb update into pipe_set_base
Passing in the old fb, having overwritten the current fb, leads to
some neatly convoluted code. It's much simpler if we defer the
crtc->fb update to the place that updates the hw, in pipe_set_base.
This way we also don't need to restore anything in case something
fails - we only update crtc->fb once things have succeeded.
The real reason for this change is that now we keep the old fb
assigned to crtc->fb, which allows us to finally move the crtc disable
case into the common low-level set_mode function in the next patch.
Also don't clobber crtc->x and crtc->y, we neatly pass these down the
callchain already. Unfortunately we can't do the same with crtc->mode,
because that one is being used in the mode_set callbacks.
v2: Don't restore the drm_crtc object any more on failed modesets,
since we've lose an fb reference otherwise. Also (and this is the
reason this has been found), this totally confused the modeset state
tracking, since it clobbers crtc->enabled. Issue reported by Paulo
Zanoni.
v3: Rip out the entire crtc saving into struct intel_set_config, not
just the restoring part.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:51:56 +08:00
|
|
|
set->x, set->y, set->fb);
|
2012-07-02 15:35:43 +08:00
|
|
|
}
|
|
|
|
|
2012-07-05 04:16:09 +08:00
|
|
|
intel_set_config_free(config);
|
|
|
|
|
2012-07-02 15:35:43 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
2012-07-05 04:24:08 +08:00
|
|
|
intel_set_config_restore_state(dev, config);
|
2012-07-02 15:35:43 +08:00
|
|
|
|
|
|
|
/* Try to restore the config */
|
2012-07-05 04:41:29 +08:00
|
|
|
if (config->mode_changed &&
|
2012-12-20 00:08:43 +08:00
|
|
|
intel_set_mode(save_set.crtc, save_set.mode,
|
|
|
|
save_set.x, save_set.y, save_set.fb))
|
2012-07-02 15:35:43 +08:00
|
|
|
DRM_ERROR("failed to restore config after modeset failure\n");
|
|
|
|
|
2012-07-05 04:16:09 +08:00
|
|
|
out_config:
|
|
|
|
intel_set_config_free(config);
|
2012-07-02 15:35:43 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2011-04-13 01:06:51 +08:00
|
|
|
|
|
|
|
static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|
|
|
.cursor_set = intel_crtc_cursor_set,
|
|
|
|
.cursor_move = intel_crtc_cursor_move,
|
|
|
|
.gamma_set = intel_crtc_gamma_set,
|
2012-07-02 15:35:43 +08:00
|
|
|
.set_config = intel_crtc_set_config,
|
2011-04-13 01:06:51 +08:00
|
|
|
.destroy = intel_crtc_destroy,
|
|
|
|
.page_flip = intel_crtc_page_flip,
|
|
|
|
};
|
|
|
|
|
2012-10-05 23:05:52 +08:00
|
|
|
static void intel_cpu_pll_init(struct drm_device *dev)
|
|
|
|
{
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev))
|
2012-10-05 23:05:52 +08:00
|
|
|
intel_ddi_pll_init(dev);
|
|
|
|
}
|
|
|
|
|
2012-04-21 00:11:53 +08:00
|
|
|
static void intel_pch_pll_init(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (dev_priv->num_pch_pll == 0) {
|
|
|
|
DRM_DEBUG_KMS("No PCH PLLs on this hardware, skipping initialisation\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < dev_priv->num_pch_pll; i++) {
|
|
|
|
dev_priv->pch_plls[i].pll_reg = _PCH_DPLL(i);
|
|
|
|
dev_priv->pch_plls[i].fp0_reg = _PCH_FP0(i);
|
|
|
|
dev_priv->pch_plls[i].fp1_reg = _PCH_FP1(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-19 04:18:47 +08:00
|
|
|
static void intel_crtc_init(struct drm_device *dev, int pipe)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2009-12-03 05:42:53 +08:00
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
|
|
|
|
if (intel_crtc == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
|
|
|
|
|
|
|
|
drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
intel_crtc->lut_r[i] = i;
|
|
|
|
intel_crtc->lut_g[i] = i;
|
|
|
|
intel_crtc->lut_b[i] = i;
|
|
|
|
}
|
|
|
|
|
2009-09-11 06:28:06 +08:00
|
|
|
/* Swap pipes & planes for FBC on pre-965 */
|
|
|
|
intel_crtc->pipe = pipe;
|
|
|
|
intel_crtc->plane = pipe;
|
2010-09-13 23:53:12 +08:00
|
|
|
if (IS_MOBILE(dev) && IS_GEN3(dev)) {
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
|
2010-09-13 23:53:12 +08:00
|
|
|
intel_crtc->plane = !pipe;
|
2009-09-11 06:28:06 +08:00
|
|
|
}
|
|
|
|
|
2009-12-03 05:42:53 +08:00
|
|
|
BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
|
|
|
|
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
|
|
|
|
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
|
|
|
|
dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
|
|
|
|
}
|
|
|
|
|
2009-04-30 05:43:54 +08:00
|
|
|
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_file *file)
|
2009-04-30 05:43:54 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
|
2009-08-11 22:05:30 +08:00
|
|
|
struct drm_mode_object *drmmode_obj;
|
|
|
|
struct intel_crtc *crtc;
|
2009-04-30 05:43:54 +08:00
|
|
|
|
2012-04-24 15:55:08 +08:00
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
|
|
return -ENODEV;
|
2009-04-30 05:43:54 +08:00
|
|
|
|
2009-08-11 22:05:30 +08:00
|
|
|
drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
|
|
|
|
DRM_MODE_OBJECT_CRTC);
|
2009-04-30 05:43:54 +08:00
|
|
|
|
2009-08-11 22:05:30 +08:00
|
|
|
if (!drmmode_obj) {
|
2009-04-30 05:43:54 +08:00
|
|
|
DRM_ERROR("no such CRTC id\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2009-08-11 22:05:30 +08:00
|
|
|
crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
|
|
|
|
pipe_from_crtc_id->pipe = crtc->pipe;
|
2009-04-30 05:43:54 +08:00
|
|
|
|
2009-08-11 22:05:30 +08:00
|
|
|
return 0;
|
2009-04-30 05:43:54 +08:00
|
|
|
}
|
|
|
|
|
2012-07-13 02:08:18 +08:00
|
|
|
static int intel_encoder_clones(struct intel_encoder *encoder)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2012-07-13 02:08:18 +08:00
|
|
|
struct drm_device *dev = encoder->base.dev;
|
|
|
|
struct intel_encoder *source_encoder;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
int index_mask = 0;
|
|
|
|
int entry = 0;
|
|
|
|
|
2012-07-13 02:08:18 +08:00
|
|
|
list_for_each_entry(source_encoder,
|
|
|
|
&dev->mode_config.encoder_list, base.head) {
|
|
|
|
|
|
|
|
if (encoder == source_encoder)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
index_mask |= (1 << entry);
|
2012-07-13 02:08:18 +08:00
|
|
|
|
|
|
|
/* Intel hw has only one MUX where enocoders could be cloned. */
|
|
|
|
if (encoder->cloneable && source_encoder->cloneable)
|
|
|
|
index_mask |= (1 << entry);
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
entry++;
|
|
|
|
}
|
2010-09-09 22:14:28 +08:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
return index_mask;
|
|
|
|
}
|
|
|
|
|
2010-12-15 03:21:29 +08:00
|
|
|
static bool has_edp_a(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
if (!IS_MOBILE(dev))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((I915_READ(DP_A) & DP_DETECTED) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (IS_GEN5(dev) &&
|
|
|
|
(I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
static void intel_setup_outputs(struct drm_device *dev)
|
|
|
|
{
|
2009-01-23 05:01:02 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-09-09 22:14:28 +08:00
|
|
|
struct intel_encoder *encoder;
|
2010-07-17 02:46:29 +08:00
|
|
|
bool dpd_is_edp = false;
|
2012-02-09 17:35:53 +08:00
|
|
|
bool has_lvds;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2012-02-09 17:35:53 +08:00
|
|
|
has_lvds = intel_lvds_init(dev);
|
2010-11-30 02:00:23 +08:00
|
|
|
if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
|
|
|
|
/* disable the panel fitter on everything but LVDS */
|
|
|
|
I915_WRITE(PFIT_CONTROL, 0);
|
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2013-04-13 05:16:53 +08:00
|
|
|
if (!IS_ULT(dev))
|
2012-11-20 23:27:40 +08:00
|
|
|
intel_crt_init(dev);
|
2010-07-17 02:46:29 +08:00
|
|
|
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev)) {
|
2012-05-10 02:37:27 +08:00
|
|
|
int found;
|
|
|
|
|
|
|
|
/* Haswell uses DDI functions to detect digital outputs */
|
|
|
|
found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED;
|
|
|
|
/* DDI A only supports eDP */
|
|
|
|
if (found)
|
|
|
|
intel_ddi_init(dev, PORT_A);
|
|
|
|
|
|
|
|
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
|
|
|
|
* register */
|
|
|
|
found = I915_READ(SFUSE_STRAP);
|
|
|
|
|
|
|
|
if (found & SFUSE_STRAP_DDIB_DETECTED)
|
|
|
|
intel_ddi_init(dev, PORT_B);
|
|
|
|
if (found & SFUSE_STRAP_DDIC_DETECTED)
|
|
|
|
intel_ddi_init(dev, PORT_C);
|
|
|
|
if (found & SFUSE_STRAP_DDID_DETECTED)
|
|
|
|
intel_ddi_init(dev, PORT_D);
|
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
2010-07-17 02:46:29 +08:00
|
|
|
int found;
|
2012-10-27 21:52:05 +08:00
|
|
|
dpd_is_edp = intel_dpd_is_edp(dev);
|
|
|
|
|
|
|
|
if (has_edp_a(dev))
|
|
|
|
intel_dp_init(dev, DP_A, PORT_A);
|
2010-07-17 02:46:29 +08:00
|
|
|
|
2013-02-20 03:21:46 +08:00
|
|
|
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
|
2010-03-30 15:11:33 +08:00
|
|
|
/* PCH SDVOB multiplex with HDMIB */
|
2012-03-24 06:43:35 +08:00
|
|
|
found = intel_sdvo_init(dev, PCH_SDVOB, true);
|
2009-06-05 15:38:43 +08:00
|
|
|
if (!found)
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
|
2009-07-24 01:00:31 +08:00
|
|
|
if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, PCH_DP_B, PORT_B);
|
2009-06-05 15:38:43 +08:00
|
|
|
}
|
|
|
|
|
2013-02-20 03:21:46 +08:00
|
|
|
if (I915_READ(PCH_HDMIC) & SDVO_DETECTED)
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, PCH_HDMIC, PORT_C);
|
2009-06-05 15:38:43 +08:00
|
|
|
|
2013-02-20 03:21:46 +08:00
|
|
|
if (!dpd_is_edp && I915_READ(PCH_HDMID) & SDVO_DETECTED)
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, PCH_HDMID, PORT_D);
|
2009-06-05 15:38:43 +08:00
|
|
|
|
2009-07-24 01:00:31 +08:00
|
|
|
if (I915_READ(PCH_DP_C) & DP_DETECTED)
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, PCH_DP_C, PORT_C);
|
2009-07-24 01:00:31 +08:00
|
|
|
|
2012-10-27 21:52:05 +08:00
|
|
|
if (I915_READ(PCH_DP_D) & DP_DETECTED)
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, PCH_DP_D, PORT_D);
|
2012-06-16 02:55:16 +08:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
2012-09-27 21:43:07 +08:00
|
|
|
/* Check for built-in panel first. Shares lanes with HDMI on SDVOC */
|
2013-01-26 03:44:44 +08:00
|
|
|
if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
|
|
|
|
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
|
2012-09-27 21:43:07 +08:00
|
|
|
|
2013-02-20 03:21:46 +08:00
|
|
|
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) {
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
|
|
|
|
PORT_B);
|
2013-01-26 03:44:44 +08:00
|
|
|
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
|
|
|
|
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
|
2012-06-16 02:55:16 +08:00
|
|
|
}
|
2009-11-27 11:44:36 +08:00
|
|
|
} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
|
2009-08-24 13:50:23 +08:00
|
|
|
bool found = false;
|
2009-01-03 05:33:00 +08:00
|
|
|
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
|
2009-12-12 03:07:17 +08:00
|
|
|
DRM_DEBUG_KMS("probing SDVOB\n");
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
found = intel_sdvo_init(dev, GEN3_SDVOB, true);
|
2009-12-12 03:07:17 +08:00
|
|
|
if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
|
|
|
|
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
|
2009-12-12 03:07:17 +08:00
|
|
|
}
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2013-05-08 18:14:08 +08:00
|
|
|
if (!found && SUPPORTS_INTEGRATED_DP(dev))
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, DP_B, PORT_B);
|
2009-01-23 05:01:02 +08:00
|
|
|
}
|
2009-03-14 03:42:14 +08:00
|
|
|
|
|
|
|
/* Before G4X SDVOC doesn't have its own detect register */
|
|
|
|
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
|
2009-12-12 03:07:17 +08:00
|
|
|
DRM_DEBUG_KMS("probing SDVOC\n");
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
found = intel_sdvo_init(dev, GEN3_SDVOC, false);
|
2009-12-12 03:07:17 +08:00
|
|
|
}
|
2009-08-24 13:50:23 +08:00
|
|
|
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2009-12-12 03:07:17 +08:00
|
|
|
if (SUPPORTS_INTEGRATED_HDMI(dev)) {
|
|
|
|
DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
|
drm/i915: clarify confusion between SDVO and HDMI registers
Some HDMI registers can be used for SDVO, so saying "HDMIB" should be
the same as saying "SDVOB" for a given HW generation. This was not
true and led to confusions and even a regression.
Previously we had:
- SDVO{B,C} defined as the Gen3+ registers
- HDMI{B,C,D} and PCH_SDVOB defined as the PCH registers
But now:
- SDVO{B,C} became GEN3_SDVO{B,C} on SDVO code
- SDVO{B,C} became GEN4_HDMI{B,C} on HDMI code
- HDMI{B,C,D} became PCH_HDMI{B,C,D}
- PCH_SDVOB is still the same thing
v2: Rebase (v1 was sent in May 2012).
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-02-19 06:00:27 +08:00
|
|
|
intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
|
2009-12-12 03:07:17 +08:00
|
|
|
}
|
2013-05-08 18:14:08 +08:00
|
|
|
if (SUPPORTS_INTEGRATED_DP(dev))
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, DP_C, PORT_C);
|
2009-01-23 05:01:02 +08:00
|
|
|
}
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2009-12-12 03:07:17 +08:00
|
|
|
if (SUPPORTS_INTEGRATED_DP(dev) &&
|
2013-05-08 18:14:08 +08:00
|
|
|
(I915_READ(DP_D) & DP_DETECTED))
|
2012-07-18 04:53:45 +08:00
|
|
|
intel_dp_init(dev, DP_D, PORT_D);
|
2009-10-23 07:11:14 +08:00
|
|
|
} else if (IS_GEN2(dev))
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
intel_dvo_init(dev);
|
|
|
|
|
2009-11-27 11:44:36 +08:00
|
|
|
if (SUPPORTS_TV(dev))
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
intel_tv_init(dev);
|
|
|
|
|
2010-09-09 22:14:28 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
|
|
|
|
encoder->base.possible_crtcs = encoder->crtc_mask;
|
|
|
|
encoder->base.possible_clones =
|
2012-07-13 02:08:18 +08:00
|
|
|
intel_encoder_clones(encoder);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2011-01-12 01:06:04 +08:00
|
|
|
|
2012-12-01 22:04:25 +08:00
|
|
|
intel_init_pch_refclk(dev);
|
2012-10-27 21:52:05 +08:00
|
|
|
|
|
|
|
drm_helper_move_panel_connectors_to_head(dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
|
|
|
{
|
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
|
|
|
|
|
|
drm_framebuffer_cleanup(fb);
|
2010-11-09 03:18:58 +08:00
|
|
|
drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
kfree(intel_fb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_file *file,
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
unsigned int *handle)
|
|
|
|
{
|
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-11-09 03:18:58 +08:00
|
|
|
return drm_gem_handle_create(file, &obj->base, handle);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct drm_framebuffer_funcs intel_fb_funcs = {
|
|
|
|
.destroy = intel_user_framebuffer_destroy,
|
|
|
|
.create_handle = intel_user_framebuffer_create_handle,
|
|
|
|
};
|
|
|
|
|
2010-03-30 13:34:13 +08:00
|
|
|
int intel_framebuffer_init(struct drm_device *dev,
|
|
|
|
struct intel_framebuffer *intel_fb,
|
2011-11-15 06:51:28 +08:00
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2012-12-19 06:13:14 +08:00
|
|
|
if (obj->tiling_mode == I915_TILING_Y) {
|
|
|
|
DRM_DEBUG("hardware does not support tiling Y\n");
|
2010-08-08 19:34:44 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2010-08-08 19:34:44 +08:00
|
|
|
|
2012-12-19 06:13:14 +08:00
|
|
|
if (mode_cmd->pitches[0] & 63) {
|
|
|
|
DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
|
|
|
|
mode_cmd->pitches[0]);
|
2010-08-08 19:34:44 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2010-08-08 19:34:44 +08:00
|
|
|
|
2012-10-31 23:50:18 +08:00
|
|
|
/* FIXME <= Gen4 stride limits are bit unclear */
|
2012-12-19 06:13:14 +08:00
|
|
|
if (mode_cmd->pitches[0] > 32768) {
|
|
|
|
DRM_DEBUG("pitch (%d) must be at less than 32768\n",
|
|
|
|
mode_cmd->pitches[0]);
|
2012-10-31 23:50:18 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2012-10-31 23:50:18 +08:00
|
|
|
|
|
|
|
if (obj->tiling_mode != I915_TILING_NONE &&
|
2012-12-19 06:13:14 +08:00
|
|
|
mode_cmd->pitches[0] != obj->stride) {
|
|
|
|
DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
|
|
|
|
mode_cmd->pitches[0], obj->stride);
|
2012-10-31 23:50:18 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2012-10-31 23:50:18 +08:00
|
|
|
|
2012-10-31 23:50:14 +08:00
|
|
|
/* Reject formats not supported by any plane early. */
|
2011-11-15 06:51:28 +08:00
|
|
|
switch (mode_cmd->pixel_format) {
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_C8:
|
2011-11-18 00:05:13 +08:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
2012-10-31 23:50:14 +08:00
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XRGB1555:
|
|
|
|
case DRM_FORMAT_ARGB1555:
|
2012-12-19 06:13:14 +08:00
|
|
|
if (INTEL_INFO(dev)->gen > 3) {
|
|
|
|
DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
|
2012-10-31 23:50:14 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2012-10-31 23:50:14 +08:00
|
|
|
break;
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
2011-11-18 00:05:13 +08:00
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
2012-10-31 23:50:14 +08:00
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
2012-12-19 06:13:14 +08:00
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
|
|
|
DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
|
2012-10-31 23:50:14 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2011-06-25 03:19:27 +08:00
|
|
|
break;
|
2011-11-18 00:05:13 +08:00
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
|
case DRM_FORMAT_UYVY:
|
|
|
|
case DRM_FORMAT_YVYU:
|
|
|
|
case DRM_FORMAT_VYUY:
|
2012-12-19 06:13:14 +08:00
|
|
|
if (INTEL_INFO(dev)->gen < 5) {
|
|
|
|
DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
|
2012-10-31 23:50:14 +08:00
|
|
|
return -EINVAL;
|
2012-12-19 06:13:14 +08:00
|
|
|
}
|
2010-08-08 19:34:44 +08:00
|
|
|
break;
|
|
|
|
default:
|
2012-12-19 06:13:14 +08:00
|
|
|
DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
|
2010-08-08 19:34:44 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2012-10-31 23:50:19 +08:00
|
|
|
/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
|
|
|
|
if (mode_cmd->offsets[0] != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-12-14 06:38:38 +08:00
|
|
|
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
|
|
|
|
intel_fb->obj = obj;
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
|
|
|
|
if (ret) {
|
|
|
|
DRM_ERROR("framebuffer init failed %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
|
intel_user_framebuffer_create(struct drm_device *dev,
|
|
|
|
struct drm_file *filp,
|
2011-11-15 06:51:28 +08:00
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2010-11-09 03:18:58 +08:00
|
|
|
struct drm_i915_gem_object *obj;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-11-15 06:51:28 +08:00
|
|
|
obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
|
|
|
|
mode_cmd->handles[0]));
|
2011-02-19 19:31:06 +08:00
|
|
|
if (&obj->base == NULL)
|
2010-08-08 20:36:38 +08:00
|
|
|
return ERR_PTR(-ENOENT);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2011-04-19 15:36:26 +08:00
|
|
|
return intel_framebuffer_create(dev, mode_cmd, obj);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct drm_mode_config_funcs intel_mode_funcs = {
|
|
|
|
.fb_create = intel_user_framebuffer_create,
|
2010-05-07 14:42:51 +08:00
|
|
|
.output_poll_changed = intel_fb_output_poll_changed,
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
};
|
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
/* Set up chip specific display functions */
|
|
|
|
static void intel_init_display(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev)) {
|
2013-03-28 17:42:00 +08:00
|
|
|
dev_priv->display.get_pipe_config = haswell_get_pipe_config;
|
2012-10-05 23:05:55 +08:00
|
|
|
dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
|
2012-10-24 04:29:51 +08:00
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
2012-10-05 23:05:58 +08:00
|
|
|
dev_priv->display.off = haswell_crtc_off;
|
2012-10-05 23:05:55 +08:00
|
|
|
dev_priv->display.update_plane = ironlake_update_plane;
|
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
2013-03-28 17:42:00 +08:00
|
|
|
dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
|
2011-03-31 04:01:02 +08:00
|
|
|
dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
|
2012-06-30 04:39:33 +08:00
|
|
|
dev_priv->display.crtc_enable = ironlake_crtc_enable;
|
|
|
|
dev_priv->display.crtc_disable = ironlake_crtc_disable;
|
2012-04-21 00:11:53 +08:00
|
|
|
dev_priv->display.off = ironlake_crtc_off;
|
2011-06-25 03:19:23 +08:00
|
|
|
dev_priv->display.update_plane = ironlake_update_plane;
|
2013-04-19 05:51:36 +08:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
|
|
|
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
|
|
|
|
dev_priv->display.crtc_enable = valleyview_crtc_enable;
|
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
|
|
|
dev_priv->display.off = i9xx_crtc_off;
|
|
|
|
dev_priv->display.update_plane = i9xx_update_plane;
|
2011-03-31 04:01:02 +08:00
|
|
|
} else {
|
2013-03-28 17:42:00 +08:00
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
2011-03-31 04:01:02 +08:00
|
|
|
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
|
2012-06-30 04:39:33 +08:00
|
|
|
dev_priv->display.crtc_enable = i9xx_crtc_enable;
|
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
2012-04-21 00:11:53 +08:00
|
|
|
dev_priv->display.off = i9xx_crtc_off;
|
2011-06-25 03:19:23 +08:00
|
|
|
dev_priv->display.update_plane = i9xx_update_plane;
|
2011-03-31 04:01:02 +08:00
|
|
|
}
|
2009-09-22 01:42:27 +08:00
|
|
|
|
|
|
|
/* Returns the core display clock speed */
|
2012-03-29 04:39:23 +08:00
|
|
|
if (IS_VALLEYVIEW(dev))
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
valleyview_get_display_clock_speed;
|
|
|
|
else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
|
2009-09-22 01:42:27 +08:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i945_get_display_clock_speed;
|
|
|
|
else if (IS_I915G(dev))
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i915_get_display_clock_speed;
|
2009-12-04 06:14:42 +08:00
|
|
|
else if (IS_I945GM(dev) || IS_845G(dev) || IS_PINEVIEW_M(dev))
|
2009-09-22 01:42:27 +08:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i9xx_misc_get_display_clock_speed;
|
|
|
|
else if (IS_I915GM(dev))
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i915gm_get_display_clock_speed;
|
|
|
|
else if (IS_I865G(dev))
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i865_get_display_clock_speed;
|
2009-09-16 04:57:33 +08:00
|
|
|
else if (IS_I85X(dev))
|
2009-09-22 01:42:27 +08:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i855_get_display_clock_speed;
|
|
|
|
else /* 852, 830 */
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
i830_get_display_clock_speed;
|
|
|
|
|
2010-04-01 13:07:53 +08:00
|
|
|
if (HAS_PCH_SPLIT(dev)) {
|
2010-10-21 21:57:17 +08:00
|
|
|
if (IS_GEN5(dev)) {
|
2011-04-29 05:27:04 +08:00
|
|
|
dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
dev_priv->display.write_eld = ironlake_write_eld;
|
2010-12-15 15:42:31 +08:00
|
|
|
} else if (IS_GEN6(dev)) {
|
2011-04-29 05:27:04 +08:00
|
|
|
dev_priv->display.fdi_link_train = gen6_fdi_link_train;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
dev_priv->display.write_eld = ironlake_write_eld;
|
2011-04-29 06:09:55 +08:00
|
|
|
} else if (IS_IVYBRIDGE(dev)) {
|
|
|
|
/* FIXME: detect B0+ stepping and use auto training */
|
|
|
|
dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
dev_priv->display.write_eld = ironlake_write_eld;
|
2012-10-27 21:58:40 +08:00
|
|
|
dev_priv->display.modeset_global_resources =
|
|
|
|
ivb_modeset_global_resources;
|
2012-05-10 02:37:21 +08:00
|
|
|
} else if (IS_HASWELL(dev)) {
|
|
|
|
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
|
2012-08-16 22:43:37 +08:00
|
|
|
dev_priv->display.write_eld = haswell_write_eld;
|
2013-01-30 02:35:20 +08:00
|
|
|
dev_priv->display.modeset_global_resources =
|
|
|
|
haswell_modeset_global_resources;
|
2012-12-06 21:12:39 +08:00
|
|
|
}
|
2011-04-29 06:04:31 +08:00
|
|
|
} else if (IS_G4X(dev)) {
|
drm/i915: pass ELD to HDMI/DP audio driver
Add ELD support for Intel Eaglelake, IbexPeak/Ironlake,
SandyBridge/CougarPoint and IvyBridge/PantherPoint chips.
ELD (EDID-Like Data) describes to the HDMI/DP audio driver the audio
capabilities of the plugged monitor. It's built and passed to audio
driver in 2 steps:
(1) at get_modes time, parse EDID and save ELD to drm_connector.eld[]
(2) at mode_set time, write drm_connector.eld[] to the Transcoder's hw
ELD buffer and set the ELD_valid bit to inform HDMI/DP audio driver
This patch is tested OK on G45/HDMI, IbexPeak/HDMI and IvyBridge/HDMI+DP.
Test scheme: plug in the HDMI/DP monitor, and run
cat /proc/asound/card0/eld*
to check if the monitor name, HDMI/DP type, etc. show up correctly.
Minor imperfection: the GEN5_AUD_CNTL_ST/DIP_Port_Select field always
reads 0 (reserved). Without knowing the port number, I worked it around
by setting the ELD_valid bit for ALL the three ports. It's tested to not
be a problem, because the audio driver will find invalid ELD data and
hence rightfully abort, even when it sees the ELD_valid indicator.
Thanks to Zhenyu and Pierre-Louis for a lot of valuable help and testing.
CC: Zhao Yakui <yakui.zhao@intel.com>
CC: Wang Zhenyu <zhenyu.z.wang@intel.com>
CC: Jeremy Bush <contractfrombelow@gmail.com>
CC: Christopher White <c.white@pulseforce.com>
CC: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
CC: Paul Menzel <paulepanter@users.sourceforge.net>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
2011-09-05 14:25:34 +08:00
|
|
|
dev_priv->display.write_eld = g4x_write_eld;
|
2009-09-22 01:42:27 +08:00
|
|
|
}
|
2011-06-17 00:19:13 +08:00
|
|
|
|
|
|
|
/* Default just returns -ENODEV to indicate unsupported */
|
|
|
|
dev_priv->display.queue_flip = intel_default_queue_flip;
|
|
|
|
|
|
|
|
switch (INTEL_INFO(dev)->gen) {
|
|
|
|
case 2:
|
|
|
|
dev_priv->display.queue_flip = intel_gen2_queue_flip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
dev_priv->display.queue_flip = intel_gen3_queue_flip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
dev_priv->display.queue_flip = intel_gen4_queue_flip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
dev_priv->display.queue_flip = intel_gen6_queue_flip;
|
|
|
|
break;
|
2011-06-17 03:18:54 +08:00
|
|
|
case 7:
|
|
|
|
dev_priv->display.queue_flip = intel_gen7_queue_flip;
|
|
|
|
break;
|
2011-06-17 00:19:13 +08:00
|
|
|
}
|
2009-09-22 01:42:27 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 04:53:12 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2011-08-17 03:34:10 +08:00
|
|
|
static void quirk_pipea_force(struct drm_device *dev)
|
2010-07-20 04:53:12 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
dev_priv->quirks |= QUIRK_PIPEA_FORCE;
|
2012-04-01 19:16:49 +08:00
|
|
|
DRM_INFO("applying pipe a force quirk\n");
|
2010-07-20 04:53:12 +08:00
|
|
|
}
|
|
|
|
|
2011-07-13 05:56:22 +08:00
|
|
|
/*
|
|
|
|
* Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
|
|
|
|
*/
|
|
|
|
static void quirk_ssc_force_disable(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE;
|
2012-04-01 19:16:49 +08:00
|
|
|
DRM_INFO("applying lvds SSC disable quirk\n");
|
2011-07-13 05:56:22 +08:00
|
|
|
}
|
|
|
|
|
2012-03-15 22:56:26 +08:00
|
|
|
/*
|
2012-03-15 22:56:27 +08:00
|
|
|
* A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight
|
|
|
|
* brightness value
|
2012-03-15 22:56:26 +08:00
|
|
|
*/
|
|
|
|
static void quirk_invert_brightness(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS;
|
2012-04-01 19:16:49 +08:00
|
|
|
DRM_INFO("applying inverted panel brightness quirk\n");
|
2011-07-13 05:56:22 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 04:53:12 +08:00
|
|
|
struct intel_quirk {
|
|
|
|
int device;
|
|
|
|
int subsystem_vendor;
|
|
|
|
int subsystem_device;
|
|
|
|
void (*hook)(struct drm_device *dev);
|
|
|
|
};
|
|
|
|
|
2012-10-14 21:46:38 +08:00
|
|
|
/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
|
|
|
|
struct intel_dmi_quirk {
|
|
|
|
void (*hook)(struct drm_device *dev);
|
|
|
|
const struct dmi_system_id (*dmi_id_list)[];
|
|
|
|
};
|
|
|
|
|
|
|
|
static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
|
|
|
|
{
|
|
|
|
DRM_INFO("Backlight polarity reversed on %s\n", id->ident);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct intel_dmi_quirk intel_dmi_quirks[] = {
|
|
|
|
{
|
|
|
|
.dmi_id_list = &(const struct dmi_system_id[]) {
|
|
|
|
{
|
|
|
|
.callback = intel_dmi_reverse_brightness,
|
|
|
|
.ident = "NCR Corporation",
|
|
|
|
.matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, ""),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ } /* terminating entry */
|
|
|
|
},
|
|
|
|
.hook = quirk_invert_brightness,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2012-04-17 05:07:40 +08:00
|
|
|
static struct intel_quirk intel_quirks[] = {
|
2010-07-20 04:53:12 +08:00
|
|
|
/* HP Mini needs pipe A force quirk (LP: #322104) */
|
2011-08-17 03:34:10 +08:00
|
|
|
{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
|
2010-07-20 04:53:12 +08:00
|
|
|
|
|
|
|
/* Toshiba Protege R-205, S-209 needs pipe A force quirk */
|
|
|
|
{ 0x2592, 0x1179, 0x0001, quirk_pipea_force },
|
|
|
|
|
|
|
|
/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
|
|
|
|
{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
|
|
|
|
|
2012-10-11 05:13:59 +08:00
|
|
|
/* 830/845 need to leave pipe A & dpll A up */
|
2010-07-20 04:53:12 +08:00
|
|
|
{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
|
2012-08-13 03:19:34 +08:00
|
|
|
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
|
2011-07-13 05:56:22 +08:00
|
|
|
|
|
|
|
/* Lenovo U160 cannot use SSC on LVDS */
|
|
|
|
{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
|
2011-07-29 00:52:06 +08:00
|
|
|
|
|
|
|
/* Sony Vaio Y cannot use SSC on LVDS */
|
|
|
|
{ 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
|
2012-03-15 22:56:27 +08:00
|
|
|
|
|
|
|
/* Acer Aspire 5734Z must invert backlight brightness */
|
|
|
|
{ 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
|
2013-01-22 18:50:34 +08:00
|
|
|
|
|
|
|
/* Acer/eMachines G725 */
|
|
|
|
{ 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
|
2013-01-22 18:50:35 +08:00
|
|
|
|
|
|
|
/* Acer/eMachines e725 */
|
|
|
|
{ 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
|
2013-01-22 18:50:36 +08:00
|
|
|
|
|
|
|
/* Acer/Packard Bell NCL20 */
|
|
|
|
{ 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
|
2013-02-16 01:35:30 +08:00
|
|
|
|
|
|
|
/* Acer Aspire 4736Z */
|
|
|
|
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
|
2010-07-20 04:53:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static void intel_init_quirks(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct pci_dev *d = dev->pdev;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
|
|
|
|
struct intel_quirk *q = &intel_quirks[i];
|
|
|
|
|
|
|
|
if (d->device == q->device &&
|
|
|
|
(d->subsystem_vendor == q->subsystem_vendor ||
|
|
|
|
q->subsystem_vendor == PCI_ANY_ID) &&
|
|
|
|
(d->subsystem_device == q->subsystem_device ||
|
|
|
|
q->subsystem_device == PCI_ANY_ID))
|
|
|
|
q->hook(dev);
|
|
|
|
}
|
2012-10-14 21:46:38 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
|
|
|
|
if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
|
|
|
|
intel_dmi_quirks[i].hook(dev);
|
|
|
|
}
|
2010-07-20 04:53:12 +08:00
|
|
|
}
|
|
|
|
|
2010-08-14 06:11:26 +08:00
|
|
|
/* Disable the VGA plane that we never use */
|
|
|
|
static void i915_disable_vga(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
u8 sr1;
|
2013-01-26 03:44:46 +08:00
|
|
|
u32 vga_reg = i915_vgacntrl_reg(dev);
|
2010-08-14 06:11:26 +08:00
|
|
|
|
|
|
|
vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
|
2012-04-07 02:46:27 +08:00
|
|
|
outb(SR01, VGA_SR_INDEX);
|
2010-08-14 06:11:26 +08:00
|
|
|
sr1 = inb(VGA_SR_DATA);
|
|
|
|
outb(sr1 | 1<<5, VGA_SR_DATA);
|
|
|
|
vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
|
|
|
|
udelay(300);
|
|
|
|
|
|
|
|
I915_WRITE(vga_reg, VGA_DISP_DISABLE);
|
|
|
|
POSTING_READ(vga_reg);
|
|
|
|
}
|
|
|
|
|
2012-04-10 21:50:11 +08:00
|
|
|
void intel_modeset_init_hw(struct drm_device *dev)
|
|
|
|
{
|
drm/i915: fix intel_init_power_wells
The current code was wrong in many different ways, so this is a full
rewrite. We don't have "different power wells for different parts of
the GPU", we have a single power well, but we have multiple registers
that can be used to request enabling/disabling the power well. So
let's be a good citizen and only use the register we're suppose to
use, except when we're loading the driver, where we clear the request
made by the BIOS.
If any of the registers is requesting the power well to be enabled, it
will be enabled. If none of the registers is requesting the power well
to be enabled, it will be disabled.
For now we're just forcing the power well to be enabled, but in the
next commits we'll change this.
V2:
- Remove debug messages that could be misleading due to possible
race conditions with KVMr, Debug and BIOS.
- Don't wait on disabling: after a conversaion with a hardware
engineer we discovered that the "restriction" on bit 31 is just
for the "enable" case, and we don't even need to wait on the
"disable" case.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-01-26 02:59:11 +08:00
|
|
|
intel_init_power_well(dev);
|
2012-07-07 02:42:36 +08:00
|
|
|
|
2012-06-29 02:55:35 +08:00
|
|
|
intel_prepare_ddi(dev);
|
|
|
|
|
2012-04-10 21:50:11 +08:00
|
|
|
intel_init_clock_gating(dev);
|
|
|
|
|
2012-06-24 22:42:33 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2012-06-24 22:42:32 +08:00
|
|
|
intel_enable_gt_powersave(dev);
|
2012-06-24 22:42:33 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2012-04-10 21:50:11 +08:00
|
|
|
}
|
|
|
|
|
2013-04-17 19:04:50 +08:00
|
|
|
void intel_modeset_suspend_hw(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
intel_suspend_hw(dev);
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
void intel_modeset_init(struct drm_device *dev)
|
|
|
|
{
|
2009-08-18 04:31:43 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-04-03 02:22:20 +08:00
|
|
|
int i, j, ret;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
|
|
|
drm_mode_config_init(dev);
|
|
|
|
|
|
|
|
dev->mode_config.min_width = 0;
|
|
|
|
dev->mode_config.min_height = 0;
|
|
|
|
|
2011-09-29 23:20:42 +08:00
|
|
|
dev->mode_config.preferred_depth = 24;
|
|
|
|
dev->mode_config.prefer_shadow = 1;
|
|
|
|
|
2012-05-17 19:27:23 +08:00
|
|
|
dev->mode_config.funcs = &intel_mode_funcs;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2010-07-20 04:53:12 +08:00
|
|
|
intel_init_quirks(dev);
|
|
|
|
|
2012-04-19 02:29:26 +08:00
|
|
|
intel_init_pm(dev);
|
|
|
|
|
2013-04-06 04:12:39 +08:00
|
|
|
if (INTEL_INFO(dev)->num_pipes == 0)
|
|
|
|
return;
|
|
|
|
|
2009-09-22 01:42:27 +08:00
|
|
|
intel_init_display(dev);
|
|
|
|
|
2010-09-17 07:32:17 +08:00
|
|
|
if (IS_GEN2(dev)) {
|
|
|
|
dev->mode_config.max_width = 2048;
|
|
|
|
dev->mode_config.max_height = 2048;
|
|
|
|
} else if (IS_GEN3(dev)) {
|
2009-07-13 14:53:17 +08:00
|
|
|
dev->mode_config.max_width = 4096;
|
|
|
|
dev->mode_config.max_height = 4096;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
} else {
|
2010-09-17 07:32:17 +08:00
|
|
|
dev->mode_config.max_width = 8192;
|
|
|
|
dev->mode_config.max_height = 8192;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2013-01-18 04:45:15 +08:00
|
|
|
dev->mode_config.fb_base = dev_priv->gtt.mappable_base;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("%d display pipe%s available.\n",
|
2013-03-14 05:05:41 +08:00
|
|
|
INTEL_INFO(dev)->num_pipes,
|
|
|
|
INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
|
2013-03-14 05:05:41 +08:00
|
|
|
for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
intel_crtc_init(dev, i);
|
2013-04-03 02:22:20 +08:00
|
|
|
for (j = 0; j < dev_priv->num_plane; j++) {
|
|
|
|
ret = intel_plane_init(dev, i, j);
|
|
|
|
if (ret)
|
2013-04-17 22:48:51 +08:00
|
|
|
DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
|
|
|
|
pipe_name(i), sprite_name(i, j), ret);
|
2013-04-03 02:22:20 +08:00
|
|
|
}
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 23:05:52 +08:00
|
|
|
intel_cpu_pll_init(dev);
|
2012-04-21 00:11:53 +08:00
|
|
|
intel_pch_pll_init(dev);
|
|
|
|
|
2010-08-14 06:11:26 +08:00
|
|
|
/* Just disable it once at startup */
|
|
|
|
i915_disable_vga(dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
intel_setup_outputs(dev);
|
2012-11-15 19:32:20 +08:00
|
|
|
|
|
|
|
/* Just in case the BIOS is doing something questionable. */
|
|
|
|
intel_disable_fbc(dev);
|
2011-03-29 17:40:27 +08:00
|
|
|
}
|
|
|
|
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
static void
|
|
|
|
intel_connector_break_all_links(struct intel_connector *connector)
|
|
|
|
{
|
|
|
|
connector->base.dpms = DRM_MODE_DPMS_OFF;
|
|
|
|
connector->base.encoder = NULL;
|
|
|
|
connector->encoder->connectors_active = false;
|
|
|
|
connector->encoder->base.crtc = NULL;
|
|
|
|
}
|
|
|
|
|
2012-07-04 23:51:47 +08:00
|
|
|
static void intel_enable_pipe_a(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct intel_connector *connector;
|
|
|
|
struct drm_connector *crt = NULL;
|
|
|
|
struct intel_load_detect_pipe load_detect_temp;
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
list_for_each_entry(connector,
|
|
|
|
&dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
|
|
|
|
crt = &connector->base;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!crt)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
|
|
|
|
intel_release_load_detect_pipe(crt, &load_detect_temp);
|
|
|
|
|
2009-08-18 04:31:43 +08:00
|
|
|
|
2012-07-04 23:51:47 +08:00
|
|
|
}
|
|
|
|
|
2012-10-11 05:14:00 +08:00
|
|
|
static bool
|
|
|
|
intel_check_plane_mapping(struct intel_crtc *crtc)
|
|
|
|
{
|
2013-03-14 05:05:41 +08:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-10-11 05:14:00 +08:00
|
|
|
u32 reg, val;
|
|
|
|
|
2013-03-14 05:05:41 +08:00
|
|
|
if (INTEL_INFO(dev)->num_pipes == 1)
|
2012-10-11 05:14:00 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
reg = DSPCNTR(!crtc->plane);
|
|
|
|
val = I915_READ(reg);
|
|
|
|
|
|
|
|
if ((val & DISPLAY_PLANE_ENABLE) &&
|
|
|
|
(!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
static void intel_sanitize_crtc(struct intel_crtc *crtc)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-10-11 05:14:00 +08:00
|
|
|
u32 reg;
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
|
|
|
|
/* Clear any frame start delays used for debugging left by the BIOS */
|
2013-04-18 02:15:07 +08:00
|
|
|
reg = PIPECONF(crtc->config.cpu_transcoder);
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
|
|
|
|
|
|
|
|
/* We need to sanitize the plane -> pipe mapping first because this will
|
2012-10-11 05:14:00 +08:00
|
|
|
* disable the crtc (and hence change the state) if it is wrong. Note
|
|
|
|
* that gen4+ has a fixed plane -> pipe mapping. */
|
|
|
|
if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
struct intel_connector *connector;
|
|
|
|
bool plane;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
|
|
|
|
crtc->base.base.id);
|
|
|
|
|
|
|
|
/* Pipe has the wrong plane attached and the plane is active.
|
|
|
|
* Temporarily change the plane mapping and disable everything
|
|
|
|
* ... */
|
|
|
|
plane = crtc->plane;
|
|
|
|
crtc->plane = !plane;
|
|
|
|
dev_priv->display.crtc_disable(&crtc->base);
|
|
|
|
crtc->plane = plane;
|
|
|
|
|
|
|
|
/* ... and break all links. */
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->encoder->base.crtc != &crtc->base)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intel_connector_break_all_links(connector);
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON(crtc->active);
|
|
|
|
crtc->base.enabled = false;
|
|
|
|
}
|
|
|
|
|
2012-07-04 23:51:47 +08:00
|
|
|
if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
|
|
|
|
crtc->pipe == PIPE_A && !crtc->active) {
|
|
|
|
/* 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. */
|
|
|
|
intel_enable_pipe_a(dev);
|
|
|
|
}
|
|
|
|
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
/* Adjust the state of the output pipe according to whether we
|
|
|
|
* have active connectors/encoders. */
|
|
|
|
intel_crtc_update_dpms(&crtc->base);
|
|
|
|
|
|
|
|
if (crtc->active != crtc->base.enabled) {
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
|
|
/* 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",
|
|
|
|
crtc->base.base.id,
|
|
|
|
crtc->base.enabled ? "enabled" : "disabled",
|
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
|
|
|
|
|
crtc->base.enabled = crtc->active;
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
WARN_ON(crtc->active);
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
|
|
|
|
WARN_ON(encoder->connectors_active);
|
|
|
|
encoder->base.crtc = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
|
|
|
{
|
|
|
|
struct intel_connector *connector;
|
|
|
|
struct drm_device *dev = encoder->base.dev;
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
bool has_active_crtc = encoder->base.crtc &&
|
|
|
|
to_intel_crtc(encoder->base.crtc)->active;
|
|
|
|
|
|
|
|
if (encoder->connectors_active && !has_active_crtc) {
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
|
|
|
|
encoder->base.base.id,
|
|
|
|
drm_get_encoder_name(&encoder->base));
|
|
|
|
|
|
|
|
/* Connector is active, but has no active pipe. This is
|
|
|
|
* fallout from our resume register restoring. Disable
|
|
|
|
* the encoder manually again. */
|
|
|
|
if (encoder->base.crtc) {
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
|
|
|
|
encoder->base.base.id,
|
|
|
|
drm_get_encoder_name(&encoder->base));
|
|
|
|
encoder->disable(encoder);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Inconsistent output/port/pipe state happens presumably due to
|
|
|
|
* 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. */
|
|
|
|
list_for_each_entry(connector,
|
|
|
|
&dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->encoder != encoder)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intel_connector_break_all_links(connector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Enabled encoders without active connectors will be fixed in
|
|
|
|
* the crtc fixup. */
|
|
|
|
}
|
|
|
|
|
2013-01-26 00:53:21 +08:00
|
|
|
void i915_redisable_vga(struct drm_device *dev)
|
2012-12-19 18:03:41 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-01-26 03:44:46 +08:00
|
|
|
u32 vga_reg = i915_vgacntrl_reg(dev);
|
2012-12-19 18:03:41 +08:00
|
|
|
|
|
|
|
if (I915_READ(vga_reg) != VGA_DISP_DISABLE) {
|
|
|
|
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
|
2013-01-26 03:44:48 +08:00
|
|
|
i915_disable_vga(dev);
|
2012-12-19 18:03:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
|
|
|
|
* and i915 state tracking structures. */
|
2012-11-24 01:16:34 +08:00
|
|
|
void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
|
bool force_restore)
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
enum pipe pipe;
|
2013-03-27 04:25:27 +08:00
|
|
|
struct drm_plane *plane;
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
struct intel_crtc *crtc;
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
struct intel_connector *connector;
|
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
|
|
|
|
base.head) {
|
2013-03-28 17:42:01 +08:00
|
|
|
memset(&crtc->config, 0, sizeof(crtc->config));
|
2013-04-18 02:15:07 +08:00
|
|
|
|
2013-03-28 17:42:00 +08:00
|
|
|
crtc->active = dev_priv->display.get_pipe_config(crtc,
|
|
|
|
&crtc->config);
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
|
|
|
|
crtc->base.enabled = crtc->active;
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
|
|
|
|
crtc->base.base.id,
|
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
|
}
|
|
|
|
|
2012-11-24 01:30:39 +08:00
|
|
|
if (HAS_DDI(dev))
|
2012-10-05 23:05:58 +08:00
|
|
|
intel_ddi_setup_hw_pll_state(dev);
|
|
|
|
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
pipe = 0;
|
|
|
|
|
|
|
|
if (encoder->get_hw_state(encoder, &pipe)) {
|
2013-05-15 08:08:26 +08:00
|
|
|
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
|
encoder->base.crtc = &crtc->base;
|
|
|
|
if (encoder->get_config)
|
|
|
|
encoder->get_config(encoder, &crtc->config);
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
} else {
|
|
|
|
encoder->base.crtc = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
encoder->connectors_active = false;
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
|
|
|
|
encoder->base.base.id,
|
|
|
|
drm_get_encoder_name(&encoder->base),
|
|
|
|
encoder->base.crtc ? "enabled" : "disabled",
|
|
|
|
pipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
|
|
|
base.head) {
|
|
|
|
if (connector->get_hw_state(connector)) {
|
|
|
|
connector->base.dpms = DRM_MODE_DPMS_ON;
|
|
|
|
connector->encoder->connectors_active = true;
|
|
|
|
connector->base.encoder = &connector->encoder->base;
|
|
|
|
} else {
|
|
|
|
connector->base.dpms = DRM_MODE_DPMS_OFF;
|
|
|
|
connector->base.encoder = NULL;
|
|
|
|
}
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
|
|
|
|
connector->base.base.id,
|
|
|
|
drm_get_connector_name(&connector->base),
|
|
|
|
connector->base.encoder ? "enabled" : "disabled");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* HW state is read out, now we need to sanitize this mess. */
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
|
|
base.head) {
|
|
|
|
intel_sanitize_encoder(encoder);
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_pipe(pipe) {
|
|
|
|
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
|
intel_sanitize_crtc(crtc);
|
2013-05-28 18:05:54 +08:00
|
|
|
intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
}
|
drm/i915: stage modeset output changes
This is the core of the new modeset logic.
The current code which is based upon the crtc helper code first
updates all the link of the new display pipeline and then calls the
lower-level set_mode function to execute the required callbacks to get
there. The issue with this approach is that for disabling we need to
know the _current_ display pipe state, not the new one.
Hence we need to stage the new state of the display pipe and only
update it once we have disabled the current configuration and before we
start to update the hw registers with the new configuration.
This patch here just prepares the ground by switching the new output
state computation to these staging pointers. To make it clearer,
rename the old update_output_state function to stage_output_state.
A few peculiarities:
- We're also calling the set_mode function at various places to update
properties. Hence after a successfule modeset we need to stage the
current configuration (for otherwise we might fall back again). This
happens automatically because as part of the (successful) modeset we
need to copy the staged state to the real one. But for the hw
readout code we need to make sure that this happens, too.
- Teach the new staged output state computation code the required
smarts to handle the disabling of outputs. The current code handles
this in a special case, but to better handle global modeset changes
covering more than one crtc, we want to do this all in the same
low-level modeset code.
- The actual modeset code is still a bit ugly and wants to know the new
crtc->enabled state a bit early. Follow-on patches will clean that
up, for now we have to apply the staged output configuration early,
outside of the set_mode functions.
- Improve/add comments in stage_output_state.
Essentially all that is left to do now is move the disabling code into
set_mode and then move the staged state update code also into
set_mode, at the right place between disabling things and calling the
mode_set callbacks for the new configuration.
v2: Disabling a crtc works by passing in a NULL mode or fb, userspace
doesn't hand in the list of connectors. We therefore need to detect
this case manually and tear down all the output links.
v3: Properly update the output staging pointers after having read out
the hw state.
v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few
assumptions with WARN_ON. Essentially all things that I've noticed
while debugging issues in other places of the code.
v4: Correctly disable the old set of connectors when enabling an
already enabled crtc on a new set of crtc. Reported by Paulo Zanoni.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-06 04:34:27 +08:00
|
|
|
|
2012-11-24 01:16:34 +08:00
|
|
|
if (force_restore) {
|
2013-04-12 02:22:50 +08:00
|
|
|
/*
|
|
|
|
* We need to use raw interfaces for restoring state to avoid
|
|
|
|
* checking (bogus) intermediate states.
|
|
|
|
*/
|
2012-11-24 01:16:34 +08:00
|
|
|
for_each_pipe(pipe) {
|
2013-03-27 04:25:27 +08:00
|
|
|
struct drm_crtc *crtc =
|
|
|
|
dev_priv->pipe_to_crtc_mapping[pipe];
|
2013-04-12 02:22:50 +08:00
|
|
|
|
|
|
|
__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
|
|
|
|
crtc->fb);
|
2012-11-24 01:16:34 +08:00
|
|
|
}
|
2013-03-27 04:25:27 +08:00
|
|
|
list_for_each_entry(plane, &dev->mode_config.plane_list, head)
|
|
|
|
intel_plane_restore(plane);
|
2012-12-19 18:03:41 +08:00
|
|
|
|
|
|
|
i915_redisable_vga(dev);
|
2012-11-24 01:16:34 +08:00
|
|
|
} else {
|
|
|
|
intel_modeset_update_staged_output_state(dev);
|
|
|
|
}
|
2012-07-10 15:50:11 +08:00
|
|
|
|
|
|
|
intel_modeset_check_state(dev);
|
2012-10-12 02:08:24 +08:00
|
|
|
|
|
|
|
drm_mode_config_reset(dev);
|
2011-03-29 17:40:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void intel_modeset_gem_init(struct drm_device *dev)
|
|
|
|
{
|
2012-05-09 18:56:28 +08:00
|
|
|
intel_modeset_init_hw(dev);
|
2009-09-16 04:57:34 +08:00
|
|
|
|
|
|
|
intel_setup_overlay(dev);
|
drm/i915: read out the modeset hw state at load and resume time
... instead of resetting a few things and hoping that this will work
out.
To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.
Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.
For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
wrapping it up.
- Reading out the pch pll connections - luckily the disable code
simply bails out if the crtc doesn't have a pch pll attached (even
for configurations that would need one).
This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.
v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.
v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.
v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.
v5: Spelling fix in a comment, noticed by Paulo Zanoni
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-07-03 02:28:59 +08:00
|
|
|
|
2012-11-24 01:16:34 +08:00
|
|
|
intel_modeset_setup_hw_state(dev, false);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void intel_modeset_cleanup(struct drm_device *dev)
|
|
|
|
{
|
2009-08-18 04:31:43 +08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
|
2013-04-24 17:13:35 +08:00
|
|
|
/*
|
|
|
|
* Interrupts and polling as the first thing to avoid creating havoc.
|
|
|
|
* Too much stuff here (turning of rps, connectors, ...) would
|
|
|
|
* experience fancy races otherwise.
|
|
|
|
*/
|
|
|
|
drm_irq_uninstall(dev);
|
|
|
|
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.
|
|
|
|
*/
|
2010-10-04 10:36:26 +08:00
|
|
|
drm_kms_helper_poll_fini(dev);
|
2013-04-24 17:13:35 +08:00
|
|
|
|
2009-08-18 04:31:43 +08:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
2010-10-08 07:01:13 +08:00
|
|
|
intel_unregister_dsm_handler();
|
|
|
|
|
2009-08-18 04:31:43 +08:00
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
|
|
/* Skip inactive CRTCs */
|
|
|
|
if (!crtc->fb)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
2010-08-21 03:40:52 +08:00
|
|
|
intel_increase_pllclock(crtc);
|
2009-08-18 04:31:43 +08:00
|
|
|
}
|
|
|
|
|
2011-07-08 19:22:37 +08:00
|
|
|
intel_disable_fbc(dev);
|
2009-09-22 01:42:27 +08:00
|
|
|
|
2012-06-24 22:42:32 +08:00
|
|
|
intel_disable_gt_powersave(dev);
|
2010-12-06 01:27:06 +08:00
|
|
|
|
2012-06-30 05:32:16 +08:00
|
|
|
ironlake_teardown_rc6(dev);
|
|
|
|
|
2009-11-12 01:19:17 +08:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
2011-07-08 19:22:42 +08:00
|
|
|
/* flush any delayed tasks or pending work */
|
|
|
|
flush_scheduled_work();
|
|
|
|
|
2013-04-12 20:18:38 +08:00
|
|
|
/* destroy backlight, if any, before the connectors */
|
|
|
|
intel_panel_destroy_backlight(dev);
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
drm_mode_config_cleanup(dev);
|
2012-12-18 22:24:37 +08:00
|
|
|
|
|
|
|
intel_cleanup_overlay(dev);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
|
|
|
|
2010-03-30 14:39:29 +08:00
|
|
|
/*
|
|
|
|
* Return which encoder is currently attached for connector.
|
|
|
|
*/
|
2010-09-09 23:20:55 +08:00
|
|
|
struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
{
|
2010-09-09 23:20:55 +08:00
|
|
|
return &intel_attached_encoder(connector)->base;
|
|
|
|
}
|
2010-03-30 14:39:29 +08:00
|
|
|
|
2010-09-09 23:20:55 +08:00
|
|
|
void intel_connector_attach_encoder(struct intel_connector *connector,
|
|
|
|
struct intel_encoder *encoder)
|
|
|
|
{
|
|
|
|
connector->encoder = encoder;
|
|
|
|
drm_mode_connector_attach_encoder(&connector->base,
|
|
|
|
&encoder->base);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-08 06:24:08 +08:00
|
|
|
}
|
2009-09-21 12:33:58 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* set vga decode state - true == enable VGA decode
|
|
|
|
*/
|
|
|
|
int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
|
|
|
|
{
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
u16 gmch_ctrl;
|
|
|
|
|
|
|
|
pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
|
|
|
|
if (state)
|
|
|
|
gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
|
|
|
|
else
|
|
|
|
gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
|
|
|
|
pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-11-21 21:12:35 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
|
|
|
struct intel_display_error_state {
|
2013-05-03 23:15:37 +08:00
|
|
|
|
|
|
|
u32 power_well_driver;
|
|
|
|
|
2010-11-21 21:12:35 +08:00
|
|
|
struct intel_cursor_error_state {
|
|
|
|
u32 control;
|
|
|
|
u32 position;
|
|
|
|
u32 base;
|
|
|
|
u32 size;
|
2012-08-16 02:23:25 +08:00
|
|
|
} cursor[I915_MAX_PIPES];
|
2010-11-21 21:12:35 +08:00
|
|
|
|
|
|
|
struct intel_pipe_error_state {
|
2013-05-03 23:15:37 +08:00
|
|
|
enum transcoder cpu_transcoder;
|
2010-11-21 21:12:35 +08:00
|
|
|
u32 conf;
|
|
|
|
u32 source;
|
|
|
|
|
|
|
|
u32 htotal;
|
|
|
|
u32 hblank;
|
|
|
|
u32 hsync;
|
|
|
|
u32 vtotal;
|
|
|
|
u32 vblank;
|
|
|
|
u32 vsync;
|
2012-08-16 02:23:25 +08:00
|
|
|
} pipe[I915_MAX_PIPES];
|
2010-11-21 21:12:35 +08:00
|
|
|
|
|
|
|
struct intel_plane_error_state {
|
|
|
|
u32 control;
|
|
|
|
u32 stride;
|
|
|
|
u32 size;
|
|
|
|
u32 pos;
|
|
|
|
u32 addr;
|
|
|
|
u32 surface;
|
|
|
|
u32 tile_offset;
|
2012-08-16 02:23:25 +08:00
|
|
|
} plane[I915_MAX_PIPES];
|
2010-11-21 21:12:35 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct intel_display_error_state *
|
|
|
|
intel_display_capture_error_state(struct drm_device *dev)
|
|
|
|
{
|
2011-08-17 03:34:10 +08:00
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
2010-11-21 21:12:35 +08:00
|
|
|
struct intel_display_error_state *error;
|
2012-10-24 04:29:59 +08:00
|
|
|
enum transcoder cpu_transcoder;
|
2010-11-21 21:12:35 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
error = kmalloc(sizeof(*error), GFP_ATOMIC);
|
|
|
|
if (error == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-05-03 23:15:37 +08:00
|
|
|
if (HAS_POWER_WELL(dev))
|
|
|
|
error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
|
|
|
|
|
2012-08-16 02:23:25 +08:00
|
|
|
for_each_pipe(i) {
|
2012-10-24 04:29:59 +08:00
|
|
|
cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
|
2013-05-03 23:15:37 +08:00
|
|
|
error->pipe[i].cpu_transcoder = cpu_transcoder;
|
2012-10-24 04:29:59 +08:00
|
|
|
|
2013-03-07 07:03:12 +08:00
|
|
|
if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
|
|
|
|
error->cursor[i].control = I915_READ(CURCNTR(i));
|
|
|
|
error->cursor[i].position = I915_READ(CURPOS(i));
|
|
|
|
error->cursor[i].base = I915_READ(CURBASE(i));
|
|
|
|
} else {
|
|
|
|
error->cursor[i].control = I915_READ(CURCNTR_IVB(i));
|
|
|
|
error->cursor[i].position = I915_READ(CURPOS_IVB(i));
|
|
|
|
error->cursor[i].base = I915_READ(CURBASE_IVB(i));
|
|
|
|
}
|
2010-11-21 21:12:35 +08:00
|
|
|
|
|
|
|
error->plane[i].control = I915_READ(DSPCNTR(i));
|
|
|
|
error->plane[i].stride = I915_READ(DSPSTRIDE(i));
|
2013-03-23 01:20:57 +08:00
|
|
|
if (INTEL_INFO(dev)->gen <= 3) {
|
2013-03-07 07:03:13 +08:00
|
|
|
error->plane[i].size = I915_READ(DSPSIZE(i));
|
2013-03-23 01:20:57 +08:00
|
|
|
error->plane[i].pos = I915_READ(DSPPOS(i));
|
|
|
|
}
|
2013-03-07 07:03:14 +08:00
|
|
|
if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
|
|
|
|
error->plane[i].addr = I915_READ(DSPADDR(i));
|
2010-11-21 21:12:35 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
error->plane[i].surface = I915_READ(DSPSURF(i));
|
|
|
|
error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
|
|
|
|
}
|
|
|
|
|
2012-10-24 04:29:59 +08:00
|
|
|
error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
|
2010-11-21 21:12:35 +08:00
|
|
|
error->pipe[i].source = I915_READ(PIPESRC(i));
|
2012-10-24 04:30:02 +08:00
|
|
|
error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
|
|
|
|
error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
|
|
|
|
error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
|
|
|
|
error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
|
|
|
|
error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
|
|
|
|
error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
|
2010-11-21 21:12:35 +08:00
|
|
|
}
|
|
|
|
|
2013-05-03 23:15:38 +08:00
|
|
|
/* 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))
|
|
|
|
I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
|
|
|
|
|
2010-11-21 21:12:35 +08:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2013-05-23 18:55:35 +08:00
|
|
|
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
|
|
|
|
|
2010-11-21 21:12:35 +08:00
|
|
|
void
|
2013-05-23 18:55:35 +08:00
|
|
|
intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
2010-11-21 21:12:35 +08:00
|
|
|
struct drm_device *dev,
|
|
|
|
struct intel_display_error_state *error)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
|
2013-05-03 23:15:37 +08:00
|
|
|
if (HAS_POWER_WELL(dev))
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, "PWR_WELL_CTL2: %08x\n",
|
2013-05-03 23:15:37 +08:00
|
|
|
error->power_well_driver);
|
2012-08-16 02:23:25 +08:00
|
|
|
for_each_pipe(i) {
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, "Pipe [%d]:\n", i);
|
|
|
|
err_printf(m, " CPU transcoder: %c\n",
|
2013-05-03 23:15:37 +08:00
|
|
|
transcoder_name(error->pipe[i].cpu_transcoder));
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, " CONF: %08x\n", error->pipe[i].conf);
|
|
|
|
err_printf(m, " SRC: %08x\n", error->pipe[i].source);
|
|
|
|
err_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal);
|
|
|
|
err_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank);
|
|
|
|
err_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync);
|
|
|
|
err_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal);
|
|
|
|
err_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank);
|
|
|
|
err_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync);
|
|
|
|
|
|
|
|
err_printf(m, "Plane [%d]:\n", i);
|
|
|
|
err_printf(m, " CNTR: %08x\n", error->plane[i].control);
|
|
|
|
err_printf(m, " STRIDE: %08x\n", error->plane[i].stride);
|
2013-03-23 01:20:57 +08:00
|
|
|
if (INTEL_INFO(dev)->gen <= 3) {
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, " SIZE: %08x\n", error->plane[i].size);
|
|
|
|
err_printf(m, " POS: %08x\n", error->plane[i].pos);
|
2013-03-23 01:20:57 +08:00
|
|
|
}
|
2013-03-23 01:19:21 +08:00
|
|
|
if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, " ADDR: %08x\n", error->plane[i].addr);
|
2010-11-21 21:12:35 +08:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, " SURF: %08x\n", error->plane[i].surface);
|
|
|
|
err_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset);
|
2010-11-21 21:12:35 +08:00
|
|
|
}
|
|
|
|
|
2013-05-23 18:55:35 +08:00
|
|
|
err_printf(m, "Cursor [%d]:\n", i);
|
|
|
|
err_printf(m, " CNTR: %08x\n", error->cursor[i].control);
|
|
|
|
err_printf(m, " POS: %08x\n", error->cursor[i].position);
|
|
|
|
err_printf(m, " BASE: %08x\n", error->cursor[i].base);
|
2010-11-21 21:12:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|