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-07 14: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 13:38:50 +02:00
|
|
|
#include <linux/dmi.h>
|
2009-09-10 15:28:03 -07: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-07 14: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 17:04:11 +09:00
|
|
|
#include <linux/slab.h>
|
2010-08-13 15:11:26 -07: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-02 18:01:07 +01: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-07 14:24:08 -08:00
|
|
|
#include "intel_drv.h"
|
2012-10-02 18:01:07 +01: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-07 14:24:08 -08:00
|
|
|
#include "i915_drv.h"
|
2010-07-01 16:48:37 -07:00
|
|
|
#include "i915_trace.h"
|
2015-03-12 20:16:32 +08:00
|
|
|
#include <drm/drm_atomic.h>
|
2015-01-21 16:35:48 -08:00
|
|
|
#include <drm/drm_atomic_helper.h>
|
2012-10-02 18:01:07 +01:00
|
|
|
#include <drm/drm_dp_helper.h>
|
|
|
|
|
#include <drm/drm_crtc_helper.h>
|
2014-05-29 08:06:54 -07:00
|
|
|
#include <drm/drm_plane_helper.h>
|
|
|
|
|
#include <drm/drm_rect.h>
|
2011-11-16 22:24:52 -08:00
|
|
|
#include <linux/dma_remapping.h>
|
2015-11-25 18:43:38 -08:00
|
|
|
#include <linux/reservation.h>
|
|
|
|
|
#include <linux/dma-buf.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-07 14:24:08 -08:00
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
/* Primary plane formats for gen <= 3 */
|
2015-05-12 16:13:18 +01:00
|
|
|
static const uint32_t i8xx_primary_formats[] = {
|
2015-05-15 19:06:00 +01:00
|
|
|
DRM_FORMAT_C8,
|
|
|
|
|
DRM_FORMAT_RGB565,
|
2014-05-29 08:06:54 -07:00
|
|
|
DRM_FORMAT_XRGB1555,
|
2015-05-15 19:06:00 +01:00
|
|
|
DRM_FORMAT_XRGB8888,
|
2014-05-29 08:06:54 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Primary plane formats for gen >= 4 */
|
2015-05-12 16:13:18 +01:00
|
|
|
static const uint32_t i965_primary_formats[] = {
|
2015-05-19 12:29:16 +01:00
|
|
|
DRM_FORMAT_C8,
|
|
|
|
|
DRM_FORMAT_RGB565,
|
|
|
|
|
DRM_FORMAT_XRGB8888,
|
|
|
|
|
DRM_FORMAT_XBGR8888,
|
|
|
|
|
DRM_FORMAT_XRGB2101010,
|
|
|
|
|
DRM_FORMAT_XBGR2101010,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint32_t skl_primary_formats[] = {
|
2015-05-15 19:06:00 +01:00
|
|
|
DRM_FORMAT_C8,
|
|
|
|
|
DRM_FORMAT_RGB565,
|
|
|
|
|
DRM_FORMAT_XRGB8888,
|
2014-05-29 08:06:54 -07:00
|
|
|
DRM_FORMAT_XBGR8888,
|
2015-05-15 19:06:00 +01:00
|
|
|
DRM_FORMAT_ARGB8888,
|
2014-05-29 08:06:54 -07:00
|
|
|
DRM_FORMAT_ABGR8888,
|
|
|
|
|
DRM_FORMAT_XRGB2101010,
|
|
|
|
|
DRM_FORMAT_XBGR2101010,
|
2015-09-03 16:17:09 +05:30
|
|
|
DRM_FORMAT_YUYV,
|
|
|
|
|
DRM_FORMAT_YVYU,
|
|
|
|
|
DRM_FORMAT_UYVY,
|
|
|
|
|
DRM_FORMAT_VYUY,
|
2014-05-29 08:06:54 -07:00
|
|
|
};
|
|
|
|
|
|
2014-06-10 08:28:13 -07:00
|
|
|
/* Cursor formats */
|
|
|
|
|
static const uint32_t intel_cursor_formats[] = {
|
|
|
|
|
DRM_FORMAT_ARGB8888,
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-27 00:39:25 +03:00
|
|
|
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config);
|
2013-09-13 16:00:08 +03:00
|
|
|
static void ironlake_pch_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config);
|
2013-06-27 00:39:25 +03:00
|
|
|
|
2014-02-12 12:26:25 -08:00
|
|
|
static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
|
|
struct intel_framebuffer *ifb,
|
|
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
|
|
struct drm_i915_gem_object *obj);
|
2014-04-24 23:55:06 +02:00
|
|
|
static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
|
|
|
|
|
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
|
2014-04-24 23:55:08 +02:00
|
|
|
static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
|
2014-08-05 07:51:22 -07:00
|
|
|
struct intel_link_m_n *m_n,
|
|
|
|
|
struct intel_link_m_n *m2_n2);
|
2014-04-24 23:55:08 +02:00
|
|
|
static void ironlake_set_pipeconf(struct drm_crtc *crtc);
|
2014-04-24 23:55:09 +02:00
|
|
|
static void haswell_set_pipeconf(struct drm_crtc *crtc);
|
|
|
|
|
static void intel_set_pipe_csc(struct drm_crtc *crtc);
|
2014-10-28 13:20:22 +02:00
|
|
|
static void vlv_prepare_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config);
|
2014-10-28 13:20:22 +02:00
|
|
|
static void chv_prepare_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config);
|
2015-07-21 13:28:58 +02:00
|
|
|
static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
|
|
|
|
|
static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
|
2015-04-07 15:28:38 -07:00
|
|
|
static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state);
|
2015-03-06 03:29:25 +02:00
|
|
|
static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
|
|
|
|
|
int num_connectors);
|
2015-08-27 15:44:05 +02:00
|
|
|
static void skylake_pfit_enable(struct intel_crtc *crtc);
|
|
|
|
|
static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
|
|
|
|
|
static void ironlake_pfit_enable(struct intel_crtc *crtc);
|
2015-07-13 16:30:25 +02:00
|
|
|
static void intel_modeset_setup_hw_state(struct drm_device *dev);
|
2015-12-03 11:37:36 -08:00
|
|
|
static void intel_pre_disable_primary(struct drm_crtc *crtc);
|
2013-08-08 22:28:59 +01: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-07 14:24:08 -08:00
|
|
|
typedef struct {
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
} intel_range_t;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
} intel_p2_t;
|
|
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
typedef struct intel_limit intel_limit_t;
|
|
|
|
|
struct intel_limit {
|
2011-08-16 15:34:10 -04:00
|
|
|
intel_range_t dot, vco, n, m, m1, m2, p, p1;
|
|
|
|
|
intel_p2_t p2;
|
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-07 14:24:08 -08:00
|
|
|
|
2015-09-24 23:29:18 +03:00
|
|
|
/* returns HPLL frequency in kHz */
|
|
|
|
|
static int valleyview_get_vco(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
|
|
|
|
|
|
|
|
|
|
/* Obtain SKU information */
|
|
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
|
|
|
|
|
CCK_FUSE_HPLL_FREQ_MASK;
|
|
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
|
|
|
|
|
return vco_freq[hpll_freq] * 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
|
|
|
|
|
const char *name, u32 reg)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
int divider;
|
|
|
|
|
|
|
|
|
|
if (dev_priv->hpll_freq == 0)
|
|
|
|
|
dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
val = vlv_cck_read(dev_priv, reg);
|
|
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
|
|
|
|
|
divider = val & CCK_FREQUENCY_VALUES;
|
|
|
|
|
|
|
|
|
|
WARN((val & CCK_FREQUENCY_STATUS) !=
|
|
|
|
|
(divider << CCK_FREQUENCY_STATUS_SHIFT),
|
|
|
|
|
"%s change in progress\n", name);
|
|
|
|
|
|
|
|
|
|
return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-20 20:57:43 +02: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-26 10:58:20 +03:00
|
|
|
/* hrawclock is 1/4 the FSB frequency */
|
|
|
|
|
int intel_hrawclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t clkcfg;
|
|
|
|
|
|
|
|
|
|
/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
2015-08-26 10:58:20 +03:00
|
|
|
return 200;
|
|
|
|
|
|
|
|
|
|
clkcfg = I915_READ(CLKCFG);
|
|
|
|
|
switch (clkcfg & CLKCFG_FSB_MASK) {
|
|
|
|
|
case CLKCFG_FSB_400:
|
|
|
|
|
return 100;
|
|
|
|
|
case CLKCFG_FSB_533:
|
|
|
|
|
return 133;
|
|
|
|
|
case CLKCFG_FSB_667:
|
|
|
|
|
return 166;
|
|
|
|
|
case CLKCFG_FSB_800:
|
|
|
|
|
return 200;
|
|
|
|
|
case CLKCFG_FSB_1067:
|
|
|
|
|
return 266;
|
|
|
|
|
case CLKCFG_FSB_1333:
|
|
|
|
|
return 333;
|
|
|
|
|
/* these two are just a guess; one of them might be right */
|
|
|
|
|
case CLKCFG_FSB_1600:
|
|
|
|
|
case CLKCFG_FSB_1600_ALT:
|
|
|
|
|
return 400;
|
|
|
|
|
default:
|
|
|
|
|
return 133;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-24 23:29:18 +03:00
|
|
|
static void intel_update_czclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
|
2015-09-24 23:29:18 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
|
|
|
|
|
CCK_CZ_CLOCK_CONTROL);
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("CZ clock rate: %d kHz\n", dev_priv->czclk_freq);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 20:54:59 +01:00
|
|
|
static inline u32 /* units of 100MHz */
|
|
|
|
|
intel_fdi_link_freq(struct drm_device *dev)
|
|
|
|
|
{
|
2010-10-13 09:59:17 +01: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-07 20:54:59 +01:00
|
|
|
}
|
|
|
|
|
|
2013-07-06 12:52:06 +02:00
|
|
|
static const intel_limit_t intel_limits_i8xx_dac = {
|
2011-08-16 15:34:10 -04:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
2013-12-09 18:54:17 +02:00
|
|
|
.vco = { .min = 908000, .max = 1512000 },
|
2013-12-09 18:54:14 +02:00
|
|
|
.n = { .min = 2, .max = 16 },
|
2011-08-16 15:34:10 -04:00
|
|
|
.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-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
|
.p2_slow = 4, .p2_fast = 2 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2013-07-06 12:52:06 +02:00
|
|
|
static const intel_limit_t intel_limits_i8xx_dvo = {
|
|
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
2013-12-09 18:54:17 +02:00
|
|
|
.vco = { .min = 908000, .max = 1512000 },
|
2013-12-09 18:54:14 +02:00
|
|
|
.n = { .min = 2, .max = 16 },
|
2013-07-06 12:52:06 +02:00
|
|
|
.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 },
|
|
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
|
.p2_slow = 4, .p2_fast = 4 },
|
|
|
|
|
};
|
|
|
|
|
|
2009-06-05 19:22:17 -07:00
|
|
|
static const intel_limit_t intel_limits_i8xx_lvds = {
|
2011-08-16 15:34:10 -04:00
|
|
|
.dot = { .min = 25000, .max = 350000 },
|
2013-12-09 18:54:17 +02:00
|
|
|
.vco = { .min = 908000, .max = 1512000 },
|
2013-12-09 18:54:14 +02:00
|
|
|
.n = { .min = 2, .max = 16 },
|
2011-08-16 15:34:10 -04:00
|
|
|
.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-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 165000,
|
|
|
|
|
.p2_slow = 14, .p2_fast = 7 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
2011-03-30 13:01:10 -07:00
|
|
|
|
2009-06-05 19:22:17 -07:00
|
|
|
static const intel_limit_t intel_limits_i9xx_sdvo = {
|
2011-08-16 15:34:10 -04:00
|
|
|
.dot = { .min = 20000, .max = 400000 },
|
|
|
|
|
.vco = { .min = 1400000, .max = 2800000 },
|
|
|
|
|
.n = { .min = 1, .max = 6 },
|
|
|
|
|
.m = { .min = 70, .max = 120 },
|
2013-02-13 22:20:22 +01:00
|
|
|
.m1 = { .min = 8, .max = 18 },
|
|
|
|
|
.m2 = { .min = 3, .max = 7 },
|
2011-08-16 15:34:10 -04:00
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 200000,
|
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_i9xx_lvds = {
|
2011-08-16 15:34:10 -04:00
|
|
|
.dot = { .min = 20000, .max = 400000 },
|
|
|
|
|
.vco = { .min = 1400000, .max = 2800000 },
|
|
|
|
|
.n = { .min = 1, .max = 6 },
|
|
|
|
|
.m = { .min = 70, .max = 120 },
|
2013-02-13 22:20:21 +01:00
|
|
|
.m1 = { .min = 8, .max = 18 },
|
|
|
|
|
.m2 = { .min = 3, .max = 7 },
|
2011-08-16 15:34:10 -04:00
|
|
|
.p = { .min = 7, .max = 98 },
|
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 112000,
|
|
|
|
|
.p2_slow = 14, .p2_fast = 7 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2011-03-30 13:01:10 -07:00
|
|
|
|
2009-06-05 19:22:17 -07:00
|
|
|
static const intel_limit_t intel_limits_g4x_sdvo = {
|
2011-03-30 13:01:10 -07: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-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_hdmi = {
|
2011-03-30 13:01:10 -07: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-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
|
2011-03-30 13:01:10 -07: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-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
|
2011-03-30 13:01:10 -07: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-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2009-12-03 17:14:42 -05:00
|
|
|
static const intel_limit_t intel_limits_pineview_sdvo = {
|
2011-08-16 15:34:10 -04:00
|
|
|
.dot = { .min = 20000, .max = 400000},
|
|
|
|
|
.vco = { .min = 1700000, .max = 3500000 },
|
2011-03-30 13:01:10 -07:00
|
|
|
/* Pineview's Ncounter is a ring counter */
|
2011-08-16 15:34:10 -04:00
|
|
|
.n = { .min = 3, .max = 6 },
|
|
|
|
|
.m = { .min = 2, .max = 256 },
|
2011-03-30 13:01:10 -07:00
|
|
|
/* Pineview only has one combined m divider, which we treat as m2. */
|
2011-08-16 15:34:10 -04:00
|
|
|
.m1 = { .min = 0, .max = 0 },
|
|
|
|
|
.m2 = { .min = 0, .max = 254 },
|
|
|
|
|
.p = { .min = 5, .max = 80 },
|
|
|
|
|
.p1 = { .min = 1, .max = 8 },
|
2011-03-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 200000,
|
|
|
|
|
.p2_slow = 10, .p2_fast = 5 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2009-12-03 17:14:42 -05:00
|
|
|
static const intel_limit_t intel_limits_pineview_lvds = {
|
2011-08-16 15:34:10 -04: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-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 112000,
|
|
|
|
|
.p2_slow = 14, .p2_fast = 14 },
|
2009-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2011-03-30 13:01:10 -07: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-30 13:01:10 -07: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-06-05 19:22:17 -07:00
|
|
|
};
|
|
|
|
|
|
2010-02-05 09:14:17 +08:00
|
|
|
static const intel_limit_t intel_limits_ironlake_single_lvds = {
|
2011-03-30 13:01:10 -07: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
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_ironlake_dual_lvds = {
|
2011-03-30 13:01:10 -07: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
|
|
|
};
|
|
|
|
|
|
2011-03-30 13:01:10 -07: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-30 13:01:10 -07: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-16 15:34:10 -04:00
|
|
|
.p1 = { .min = 2, .max = 8 },
|
2011-03-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
|
.p2_slow = 14, .p2_fast = 14 },
|
2010-02-05 09:14:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
|
2011-03-30 13:01:10 -07: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-16 15:34:10 -04:00
|
|
|
.p1 = { .min = 2, .max = 6 },
|
2011-03-30 13:01:10 -07:00
|
|
|
.p2 = { .dot_limit = 225000,
|
|
|
|
|
.p2_slow = 7, .p2_fast = 7 },
|
2009-12-31 16:06:04 +08:00
|
|
|
};
|
|
|
|
|
|
2013-09-24 21:26:30 +03:00
|
|
|
static const intel_limit_t intel_limits_vlv = {
|
2013-09-27 16:55:49 +03:00
|
|
|
/*
|
|
|
|
|
* These are the data rate limits (measured in fast clocks)
|
|
|
|
|
* since those are the strictest limits we have. The fast
|
|
|
|
|
* clock and actual rate limits are more relaxed, so checking
|
|
|
|
|
* them would make no difference.
|
|
|
|
|
*/
|
|
|
|
|
.dot = { .min = 25000 * 5, .max = 270000 * 5 },
|
2013-04-18 21:10:43 +02:00
|
|
|
.vco = { .min = 4000000, .max = 6000000 },
|
2012-06-15 11:55:13 -07:00
|
|
|
.n = { .min = 1, .max = 7 },
|
|
|
|
|
.m1 = { .min = 2, .max = 3 },
|
|
|
|
|
.m2 = { .min = 11, .max = 156 },
|
2013-09-24 21:26:26 +03:00
|
|
|
.p1 = { .min = 2, .max = 3 },
|
2013-09-24 21:26:29 +03:00
|
|
|
.p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */
|
2012-06-15 11:55:13 -07:00
|
|
|
};
|
|
|
|
|
|
2014-04-09 13:28:18 +03:00
|
|
|
static const intel_limit_t intel_limits_chv = {
|
|
|
|
|
/*
|
|
|
|
|
* These are the data rate limits (measured in fast clocks)
|
|
|
|
|
* since those are the strictest limits we have. The fast
|
|
|
|
|
* clock and actual rate limits are more relaxed, so checking
|
|
|
|
|
* them would make no difference.
|
|
|
|
|
*/
|
|
|
|
|
.dot = { .min = 25000 * 5, .max = 540000 * 5},
|
2015-02-26 21:01:52 +02:00
|
|
|
.vco = { .min = 4800000, .max = 6480000 },
|
2014-04-09 13:28:18 +03:00
|
|
|
.n = { .min = 1, .max = 1 },
|
|
|
|
|
.m1 = { .min = 2, .max = 2 },
|
|
|
|
|
.m2 = { .min = 24 << 22, .max = 175 << 22 },
|
|
|
|
|
.p1 = { .min = 2, .max = 4 },
|
|
|
|
|
.p2 = { .p2_slow = 1, .p2_fast = 14 },
|
|
|
|
|
};
|
|
|
|
|
|
2015-03-06 03:29:25 +02:00
|
|
|
static const intel_limit_t intel_limits_bxt = {
|
|
|
|
|
/* FIXME: find real dot limits */
|
|
|
|
|
.dot = { .min = 0, .max = INT_MAX },
|
2015-07-01 17:02:57 +05:30
|
|
|
.vco = { .min = 4800000, .max = 6700000 },
|
2015-03-06 03:29:25 +02:00
|
|
|
.n = { .min = 1, .max = 1 },
|
|
|
|
|
.m1 = { .min = 2, .max = 2 },
|
|
|
|
|
/* FIXME: find real m2 limits */
|
|
|
|
|
.m2 = { .min = 2 << 22, .max = 255 << 22 },
|
|
|
|
|
.p1 = { .min = 2, .max = 4 },
|
|
|
|
|
.p2 = { .p2_slow = 1, .p2_fast = 20 },
|
|
|
|
|
};
|
|
|
|
|
|
2015-06-01 12:49:51 +02:00
|
|
|
static bool
|
|
|
|
|
needs_modeset(struct drm_crtc_state *state)
|
|
|
|
|
{
|
2015-07-21 13:28:57 +02:00
|
|
|
return drm_atomic_crtc_needs_modeset(state);
|
2015-06-01 12:49:51 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-24 13:52:54 -03:00
|
|
|
/**
|
|
|
|
|
* Returns whether any output on the specified pipe is of the specified type
|
|
|
|
|
*/
|
2014-10-29 11:16:59 +00:00
|
|
|
bool intel_pipe_has_type(struct intel_crtc *crtc, enum intel_output_type type)
|
2013-09-24 13:52:54 -03:00
|
|
|
{
|
2014-10-20 13:46:45 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2013-09-24 13:52:54 -03:00
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
2014-10-20 13:46:45 +03:00
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
2013-09-24 13:52:54 -03:00
|
|
|
if (encoder->type == type)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-29 11:32:30 +02:00
|
|
|
/**
|
|
|
|
|
* Returns whether any output on the specified pipe will have the specified
|
|
|
|
|
* type after a staged modeset is complete, i.e., the same as
|
|
|
|
|
* intel_pipe_has_type() but looking at encoder->new_crtc instead of
|
|
|
|
|
* encoder->crtc.
|
|
|
|
|
*/
|
2015-03-20 16:18:17 +02:00
|
|
|
static bool intel_pipe_will_have_type(const struct intel_crtc_state *crtc_state,
|
|
|
|
|
int type)
|
2014-10-29 11:32:30 +02:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_atomic_state *state = crtc_state->base.state;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
2014-10-29 11:32:30 +02:00
|
|
|
struct intel_encoder *encoder;
|
2015-03-20 16:18:17 +02:00
|
|
|
int i, num_connectors = 0;
|
|
|
|
|
|
2015-04-21 17:12:59 +03:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
2015-03-20 16:18:17 +02:00
|
|
|
if (connector_state->crtc != crtc_state->base.crtc)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
num_connectors++;
|
2014-10-29 11:32:30 +02:00
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
if (encoder->type == type)
|
2014-10-29 11:32:30 +02:00
|
|
|
return true;
|
2015-03-20 16:18:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WARN_ON(num_connectors == 0);
|
2014-10-29 11:32:30 +02:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
static const intel_limit_t *
|
|
|
|
|
intel_ironlake_limit(struct intel_crtc_state *crtc_state, int refclk)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
2009-06-05 15:38:42 +08:00
|
|
|
const intel_limit_t *limit;
|
2010-02-05 09:14:17 +08:00
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
|
2012-11-26 17:22:09 +01:00
|
|
|
if (intel_is_dual_link_lvds(dev)) {
|
2010-12-14 20:04:54 +00: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-14 20:04:54 +00: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 11:14:33 +02: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
static const intel_limit_t *
|
|
|
|
|
intel_g4x_limit(struct intel_crtc_state *crtc_state)
|
2009-03-18 20:13:23 +08:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
2009-03-18 20:13:23 +08:00
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
|
2012-11-26 17:22:09 +01:00
|
|
|
if (intel_is_dual_link_lvds(dev))
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_g4x_dual_channel_lvds;
|
2009-03-18 20:13:23 +08:00
|
|
|
else
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_g4x_single_channel_lvds;
|
2015-03-20 16:18:17 +02:00
|
|
|
} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) ||
|
|
|
|
|
intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_g4x_hdmi;
|
2015-03-20 16:18:17 +02:00
|
|
|
} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) {
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_g4x_sdvo;
|
2009-03-18 20:13:23 +08:00
|
|
|
} else /* The option is for other outputs */
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_i9xx_sdvo;
|
2009-03-18 20:13:23 +08:00
|
|
|
|
|
|
|
|
return limit;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
static const intel_limit_t *
|
|
|
|
|
intel_limit(struct intel_crtc_state *crtc_state, 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-07 14:24:08 -08:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->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-07 14:24:08 -08:00
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
|
2015-03-06 03:29:25 +02:00
|
|
|
if (IS_BROXTON(dev))
|
|
|
|
|
limit = &intel_limits_bxt;
|
|
|
|
|
else if (HAS_PCH_SPLIT(dev))
|
2015-03-20 16:18:17 +02:00
|
|
|
limit = intel_ironlake_limit(crtc_state, refclk);
|
2009-06-05 15:38:42 +08:00
|
|
|
else if (IS_G4X(dev)) {
|
2015-03-20 16:18:17 +02:00
|
|
|
limit = intel_g4x_limit(crtc_state);
|
2009-12-03 17:14:42 -05:00
|
|
|
} else if (IS_PINEVIEW(dev)) {
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
|
2009-12-03 17:14:42 -05:00
|
|
|
limit = &intel_limits_pineview_lvds;
|
2009-02-23 15:19:16 +08:00
|
|
|
else
|
2009-12-03 17:14:42 -05:00
|
|
|
limit = &intel_limits_pineview_sdvo;
|
2014-04-09 13:28:18 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev)) {
|
|
|
|
|
limit = &intel_limits_chv;
|
2012-06-15 11:55:13 -07:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
2013-09-24 21:26:30 +03:00
|
|
|
limit = &intel_limits_vlv;
|
2010-09-17 00:32:17 +01:00
|
|
|
} else if (!IS_GEN2(dev)) {
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
|
2010-09-17 00:32:17 +01:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
} else {
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_i8xx_lvds;
|
2015-03-20 16:18:17 +02:00
|
|
|
else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO))
|
2009-06-05 19:22:17 -07:00
|
|
|
limit = &intel_limits_i8xx_dvo;
|
2013-07-06 12:52:06 +02:00
|
|
|
else
|
|
|
|
|
limit = &intel_limits_i8xx_dac;
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
return limit;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
/*
|
|
|
|
|
* Platform specific helpers to calculate the port PLL loopback- (clock.m),
|
|
|
|
|
* and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
|
|
|
|
|
* (clock.dot) clock rates. This fast dot clock is fed to the port's IO logic.
|
|
|
|
|
* The helpers' return value is the rate of the clock that is fed to the
|
|
|
|
|
* display engine's pipe which can be the above fast dot clock rate or a
|
|
|
|
|
* divided-down version of it.
|
|
|
|
|
*/
|
2009-12-03 17:14:42 -05:00
|
|
|
/* m1 is reserved as 0 in Pineview, n is a ring counter */
|
2015-06-22 23:35:51 +03:00
|
|
|
static int pnv_calc_dpll_params(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-07 14:24:08 -08:00
|
|
|
{
|
2009-02-23 15:19:16 +08:00
|
|
|
clock->m = clock->m2 + 2;
|
|
|
|
|
clock->p = clock->p1 * clock->p2;
|
2013-12-02 19:00:45 +02:00
|
|
|
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
2015-06-22 23:35:51 +03:00
|
|
|
return 0;
|
2013-10-14 14:50:30 +03:00
|
|
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
|
|
|
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
2015-06-22 23:35:51 +03:00
|
|
|
|
|
|
|
|
return clock->dot;
|
2009-02-23 15:19:16 +08:00
|
|
|
}
|
|
|
|
|
|
2013-04-20 17:19:46 +02:00
|
|
|
static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
|
|
|
|
|
{
|
|
|
|
|
return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
static int i9xx_calc_dpll_params(int refclk, intel_clock_t *clock)
|
2009-02-23 15:19:16 +08:00
|
|
|
{
|
2013-04-20 17:19:46 +02: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-07 14:24:08 -08:00
|
|
|
clock->p = clock->p1 * clock->p2;
|
2013-12-02 19:00:45 +02:00
|
|
|
if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
|
2015-06-22 23:35:51 +03:00
|
|
|
return 0;
|
2013-10-14 14:50:30 +03:00
|
|
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
|
|
|
|
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
2015-06-22 23:35:51 +03:00
|
|
|
|
|
|
|
|
return clock->dot;
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
static int vlv_calc_dpll_params(int refclk, intel_clock_t *clock)
|
2015-06-22 23:35:50 +03:00
|
|
|
{
|
|
|
|
|
clock->m = clock->m1 * clock->m2;
|
|
|
|
|
clock->p = clock->p1 * clock->p2;
|
|
|
|
|
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
2015-06-22 23:35:51 +03:00
|
|
|
return 0;
|
2015-06-22 23:35:50 +03:00
|
|
|
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
|
|
|
|
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
2015-06-22 23:35:51 +03:00
|
|
|
|
|
|
|
|
return clock->dot / 5;
|
2015-06-22 23:35:50 +03:00
|
|
|
}
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
int chv_calc_dpll_params(int refclk, intel_clock_t *clock)
|
2014-04-09 13:28:18 +03:00
|
|
|
{
|
|
|
|
|
clock->m = clock->m1 * clock->m2;
|
|
|
|
|
clock->p = clock->p1 * clock->p2;
|
|
|
|
|
if (WARN_ON(clock->n == 0 || clock->p == 0))
|
2015-06-22 23:35:51 +03:00
|
|
|
return 0;
|
2014-04-09 13:28:18 +03:00
|
|
|
clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m,
|
|
|
|
|
clock->n << 22);
|
|
|
|
|
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
|
2015-06-22 23:35:51 +03:00
|
|
|
|
|
|
|
|
return clock->dot / 5;
|
2014-04-09 13:28:18 +03:00
|
|
|
}
|
|
|
|
|
|
2009-02-23 15: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-07 14:24:08 -08:00
|
|
|
/**
|
|
|
|
|
* Returns whether the given set of divisors are valid for a given refclk with
|
|
|
|
|
* the given connectors.
|
|
|
|
|
*/
|
|
|
|
|
|
2010-12-14 20:04:54 +00: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-07 14:24:08 -08:00
|
|
|
{
|
2013-09-27 16:55:49 +03:00
|
|
|
if (clock->n < limit->n.min || limit->n.max < clock->n)
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
|
2011-08-16 15:34:10 -04:00
|
|
|
INTELPllInvalid("m1 out of range\n");
|
2013-09-27 16:55:49 +03:00
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
|
|
|
|
|
!IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
|
2013-09-27 16:55:49 +03:00
|
|
|
if (clock->m1 <= clock->m2)
|
|
|
|
|
INTELPllInvalid("m1 <= m2\n");
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
|
2013-09-27 16:55:49 +03:00
|
|
|
if (clock->p < limit->p.min || limit->p.max < clock->p)
|
|
|
|
|
INTELPllInvalid("p out of range\n");
|
|
|
|
|
if (clock->m < limit->m.min || limit->m.max < clock->m)
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
|
2011-08-16 15:34:10 -04: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-07 14: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-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 13:47:22 +03:00
|
|
|
static int
|
|
|
|
|
i9xx_select_p2_div(const intel_limit_t *limit,
|
|
|
|
|
const struct intel_crtc_state *crtc_state,
|
|
|
|
|
int target)
|
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-07 14:24:08 -08:00
|
|
|
{
|
2015-06-18 13:47:22 +03:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->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-07 14:24:08 -08:00
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, 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-07 14:24:08 -08:00
|
|
|
/*
|
2012-11-26 17:22:08 +01: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-07 14:24:08 -08:00
|
|
|
*/
|
2012-11-26 17:22:09 +01:00
|
|
|
if (intel_is_dual_link_lvds(dev))
|
2015-06-18 13:47:22 +03:00
|
|
|
return limit->p2.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-07 14:24:08 -08:00
|
|
|
else
|
2015-06-18 13:47:22 +03:00
|
|
|
return limit->p2.p2_slow;
|
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-07 14:24:08 -08:00
|
|
|
} else {
|
|
|
|
|
if (target < limit->p2.dot_limit)
|
2015-06-18 13:47:22 +03:00
|
|
|
return limit->p2.p2_slow;
|
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-07 14:24:08 -08:00
|
|
|
else
|
2015-06-18 13:47:22 +03:00
|
|
|
return limit->p2.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-07 14:24:08 -08:00
|
|
|
}
|
2015-06-18 13:47:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
i9xx_find_best_dpll(const intel_limit_t *limit,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
|
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
|
intel_clock_t *best_clock)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
|
|
|
|
intel_clock_t clock;
|
|
|
|
|
int err = target;
|
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-07 14:24:08 -08:00
|
|
|
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
|
2015-06-18 13:47:22 +03:00
|
|
|
clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
|
|
|
|
|
|
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++) {
|
2013-06-03 20:56:24 +02:00
|
|
|
if (clock.m2 >= clock.m1)
|
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-07 14:24:08 -08:00
|
|
|
int this_err;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
i9xx_calc_dpll_params(refclk, &clock);
|
2013-06-01 17:16:17 +02:00
|
|
|
if (!intel_PLL_is_valid(dev, limit,
|
|
|
|
|
&clock))
|
|
|
|
|
continue;
|
|
|
|
|
if (match_clock &&
|
|
|
|
|
clock.p != match_clock->p)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
this_err = abs(clock.dot - target);
|
|
|
|
|
if (this_err < err) {
|
|
|
|
|
*best_clock = clock;
|
|
|
|
|
err = this_err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (err != target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
2015-03-20 16:18:17 +02:00
|
|
|
pnv_find_best_dpll(const intel_limit_t *limit,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
2013-06-03 22:40:22 +02: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-07 14:24:08 -08:00
|
|
|
{
|
2015-06-18 13:47:22 +03:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->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-07 14:24:08 -08:00
|
|
|
intel_clock_t clock;
|
|
|
|
|
int err = target;
|
|
|
|
|
|
2011-08-16 15:34:10 -04: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-07 14:24:08 -08:00
|
|
|
|
2015-06-18 13:47:22 +03:00
|
|
|
clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
|
|
|
|
|
|
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++) {
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
int this_err;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
pnv_calc_dpll_params(refclk, &clock);
|
2010-12-14 20:04:54 +00: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-07 14:24:08 -08:00
|
|
|
continue;
|
2012-01-10 15: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-07 14: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
|
2015-03-20 16:18:17 +02:00
|
|
|
g4x_find_best_dpll(const intel_limit_t *limit,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
2013-06-03 22:40:22 +02:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
|
intel_clock_t *best_clock)
|
2009-03-18 20:13:27 +08:00
|
|
|
{
|
2015-06-18 13:47:22 +03:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
2009-03-18 20:13:27 +08:00
|
|
|
intel_clock_t clock;
|
|
|
|
|
int max_n;
|
2015-06-18 13:47:22 +03:00
|
|
|
bool found = false;
|
2010-07-02 16:43:30 -04:00
|
|
|
/* approximately equals target * 0.00585 */
|
|
|
|
|
int err_most = (target >> 8) + (target >> 9);
|
2009-03-18 20:13:27 +08:00
|
|
|
|
|
|
|
|
memset(best_clock, 0, sizeof(*best_clock));
|
2015-06-18 13:47:22 +03:00
|
|
|
|
|
|
|
|
clock.p2 = i9xx_select_p2_div(limit, crtc_state, target);
|
|
|
|
|
|
2009-03-18 20:13:27 +08:00
|
|
|
max_n = limit->n.max;
|
2010-03-29 15:41:47 +02: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 15:41:47 +02: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;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
i9xx_calc_dpll_params(refclk, &clock);
|
2010-12-14 20:04:54 +00:00
|
|
|
if (!intel_PLL_is_valid(dev, limit,
|
|
|
|
|
&clock))
|
2009-03-18 20:13:27 +08:00
|
|
|
continue;
|
2010-12-14 20:04:54 +00: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-17 11:40:03 +02:00
|
|
|
/*
|
|
|
|
|
* Check if the calculated PLL configuration is more optimal compared to the
|
|
|
|
|
* best configuration and error found so far. Return the calculated error.
|
|
|
|
|
*/
|
|
|
|
|
static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
|
|
|
|
|
const intel_clock_t *calculated_clock,
|
|
|
|
|
const intel_clock_t *best_clock,
|
|
|
|
|
unsigned int best_error_ppm,
|
|
|
|
|
unsigned int *error_ppm)
|
|
|
|
|
{
|
2015-03-17 11:40:05 +02:00
|
|
|
/*
|
|
|
|
|
* For CHV ignore the error and consider only the P value.
|
|
|
|
|
* Prefer a bigger P value based on HW requirements.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
|
|
|
|
*error_ppm = 0;
|
|
|
|
|
|
|
|
|
|
return calculated_clock->p > best_clock->p;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-17 11:40:04 +02:00
|
|
|
if (WARN_ON_ONCE(!target_freq))
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-03-17 11:40:03 +02:00
|
|
|
*error_ppm = div_u64(1000000ULL *
|
|
|
|
|
abs(target_freq - calculated_clock->dot),
|
|
|
|
|
target_freq);
|
|
|
|
|
/*
|
|
|
|
|
* Prefer a better P value over a better (smaller) error if the error
|
|
|
|
|
* is small. Ensure this preference for future configurations too by
|
|
|
|
|
* setting the error to 0.
|
|
|
|
|
*/
|
|
|
|
|
if (*error_ppm < 100 && calculated_clock->p > best_clock->p) {
|
|
|
|
|
*error_ppm = 0;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *error_ppm + 10 < best_error_ppm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-15 11:55:13 -07:00
|
|
|
static bool
|
2015-03-20 16:18:17 +02:00
|
|
|
vlv_find_best_dpll(const intel_limit_t *limit,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
2013-06-03 22:40:22 +02:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
|
intel_clock_t *best_clock)
|
2012-06-15 11:55:13 -07:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
2014-10-20 13:46:43 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2013-09-27 16:54:19 +03:00
|
|
|
intel_clock_t clock;
|
2013-09-24 21:26:20 +03:00
|
|
|
unsigned int bestppm = 1000000;
|
2013-09-24 21:26:24 +03:00
|
|
|
/* min update 19.2 MHz */
|
|
|
|
|
int max_n = min(limit->n.max, refclk / 19200);
|
2013-09-24 21:26:31 +03:00
|
|
|
bool found = false;
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2013-09-27 16:54:19 +03:00
|
|
|
target *= 5; /* fast clock */
|
|
|
|
|
|
|
|
|
|
memset(best_clock, 0, sizeof(*best_clock));
|
2012-06-15 11:55:13 -07:00
|
|
|
|
|
|
|
|
/* based on hardware requirement, prefer smaller n to precision */
|
2013-09-24 21:26:24 +03:00
|
|
|
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
2013-09-24 21:26:25 +03:00
|
|
|
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
2013-09-24 21:26:27 +03:00
|
|
|
for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow;
|
2013-09-24 21:26:23 +03:00
|
|
|
clock.p2 -= clock.p2 > 10 ? 2 : 1) {
|
2013-09-27 16:54:19 +03:00
|
|
|
clock.p = clock.p1 * clock.p2;
|
2012-06-15 11:55:13 -07:00
|
|
|
/* based on hardware requirement, prefer bigger m1,m2 values */
|
2013-09-27 16:54:19 +03:00
|
|
|
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
|
2015-03-17 11:40:03 +02:00
|
|
|
unsigned int ppm;
|
2013-09-24 21:26:20 +03:00
|
|
|
|
2013-09-27 16:54:19 +03:00
|
|
|
clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
|
|
|
|
|
refclk * clock.m1);
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
vlv_calc_dpll_params(refclk, &clock);
|
2013-09-24 21:26:18 +03:00
|
|
|
|
2013-09-27 16:55:49 +03:00
|
|
|
if (!intel_PLL_is_valid(dev, limit,
|
|
|
|
|
&clock))
|
2013-09-24 21:26:18 +03:00
|
|
|
continue;
|
|
|
|
|
|
2015-03-17 11:40:03 +02:00
|
|
|
if (!vlv_PLL_is_optimal(dev, target,
|
|
|
|
|
&clock,
|
|
|
|
|
best_clock,
|
|
|
|
|
bestppm, &ppm))
|
|
|
|
|
continue;
|
2013-09-27 16:54:19 +03:00
|
|
|
|
2015-03-17 11:40:03 +02:00
|
|
|
*best_clock = clock;
|
|
|
|
|
bestppm = ppm;
|
|
|
|
|
found = true;
|
2012-06-15 11:55:13 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-24 21:26:31 +03:00
|
|
|
return found;
|
2012-06-15 11:55:13 -07:00
|
|
|
}
|
2009-04-07 16:16:42 -07:00
|
|
|
|
2014-04-09 13:28:18 +03:00
|
|
|
static bool
|
2015-03-20 16:18:17 +02:00
|
|
|
chv_find_best_dpll(const intel_limit_t *limit,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
2014-04-09 13:28:18 +03:00
|
|
|
int target, int refclk, intel_clock_t *match_clock,
|
|
|
|
|
intel_clock_t *best_clock)
|
|
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
2014-10-20 13:46:43 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2015-03-17 11:40:05 +02:00
|
|
|
unsigned int best_error_ppm;
|
2014-04-09 13:28:18 +03:00
|
|
|
intel_clock_t clock;
|
|
|
|
|
uint64_t m2;
|
|
|
|
|
int found = false;
|
|
|
|
|
|
|
|
|
|
memset(best_clock, 0, sizeof(*best_clock));
|
2015-03-17 11:40:05 +02:00
|
|
|
best_error_ppm = 1000000;
|
2014-04-09 13:28:18 +03:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Based on hardware doc, the n always set to 1, and m1 always
|
|
|
|
|
* set to 2. If requires to support 200Mhz refclk, we need to
|
|
|
|
|
* revisit this because n may not 1 anymore.
|
|
|
|
|
*/
|
|
|
|
|
clock.n = 1, clock.m1 = 2;
|
|
|
|
|
target *= 5; /* fast clock */
|
|
|
|
|
|
|
|
|
|
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
|
|
|
|
for (clock.p2 = limit->p2.p2_fast;
|
|
|
|
|
clock.p2 >= limit->p2.p2_slow;
|
|
|
|
|
clock.p2 -= clock.p2 > 10 ? 2 : 1) {
|
2015-03-17 11:40:05 +02:00
|
|
|
unsigned int error_ppm;
|
2014-04-09 13:28:18 +03:00
|
|
|
|
|
|
|
|
clock.p = clock.p1 * clock.p2;
|
|
|
|
|
|
|
|
|
|
m2 = DIV_ROUND_CLOSEST_ULL(((uint64_t)target * clock.p *
|
|
|
|
|
clock.n) << 22, refclk * clock.m1);
|
|
|
|
|
|
|
|
|
|
if (m2 > INT_MAX/clock.m1)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
clock.m2 = m2;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
chv_calc_dpll_params(refclk, &clock);
|
2014-04-09 13:28:18 +03:00
|
|
|
|
|
|
|
|
if (!intel_PLL_is_valid(dev, limit, &clock))
|
|
|
|
|
continue;
|
|
|
|
|
|
2015-03-17 11:40:05 +02:00
|
|
|
if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
|
|
|
|
|
best_error_ppm, &error_ppm))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
*best_clock = clock;
|
|
|
|
|
best_error_ppm = error_ppm;
|
|
|
|
|
found = true;
|
2014-04-09 13:28:18 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 03:29:25 +02:00
|
|
|
bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
|
|
|
|
|
intel_clock_t *best_clock)
|
|
|
|
|
{
|
|
|
|
|
int refclk = i9xx_get_refclk(crtc_state, 0);
|
|
|
|
|
|
|
|
|
|
return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state,
|
|
|
|
|
target_clock, refclk, NULL, best_clock);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-04 18:25:25 +03:00
|
|
|
bool intel_crtc_active(struct drm_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
|
|
/* Be paranoid as we can arrive here with only partial
|
|
|
|
|
* state retrieved from the hardware during setup.
|
|
|
|
|
*
|
2013-09-25 16:45:37 +01:00
|
|
|
* We can ditch the adjusted_mode.crtc_clock check as soon
|
2013-09-04 18:25:25 +03:00
|
|
|
* as Haswell has gained clock readout/fastboot support.
|
|
|
|
|
*
|
2014-04-03 07:51:54 +10:00
|
|
|
* We can ditch the crtc->primary->fb check as soon as we can
|
2013-09-04 18:25:25 +03:00
|
|
|
* properly reconstruct framebuffers.
|
2015-03-09 10:19:23 -07:00
|
|
|
*
|
|
|
|
|
* FIXME: The intel_crtc->active here should be switched to
|
|
|
|
|
* crtc->state->active once we have proper CRTC states wired up
|
|
|
|
|
* for atomic.
|
2013-09-04 18:25:25 +03:00
|
|
|
*/
|
2015-03-09 10:19:23 -07:00
|
|
|
return intel_crtc->active && crtc->primary->state->fb &&
|
2015-01-15 14:55:25 +02:00
|
|
|
intel_crtc->config->base.adjusted_mode.crtc_clock;
|
2013-09-04 18:25:25 +03: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-24 15:59:34 -02: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);
|
|
|
|
|
|
2015-01-15 14:55:25 +02: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-24 15:59:34 -02:00
|
|
|
}
|
|
|
|
|
|
2013-10-11 14:21:31 +03:00
|
|
|
static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = PIPEDSL(pipe);
|
2013-10-11 14:21:31 +03:00
|
|
|
u32 line1, line2;
|
|
|
|
|
u32 line_mask;
|
|
|
|
|
|
|
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
line_mask = DSL_LINEMASK_GEN2;
|
|
|
|
|
else
|
|
|
|
|
line_mask = DSL_LINEMASK_GEN3;
|
|
|
|
|
|
|
|
|
|
line1 = I915_READ(reg) & line_mask;
|
2015-07-07 09:10:40 +02:00
|
|
|
msleep(5);
|
2013-10-11 14:21:31 +03:00
|
|
|
line2 = I915_READ(reg) & line_mask;
|
|
|
|
|
|
|
|
|
|
return line1 == line2;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-03 00:33:06 -07:00
|
|
|
/*
|
|
|
|
|
* intel_wait_for_pipe_off - wait for pipe to turn off
|
2014-08-15 01:21:56 +03:00
|
|
|
* @crtc: crtc whose pipe to wait for
|
2010-08-18 13:20:54 -07:00
|
|
|
*
|
|
|
|
|
* 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 00:33:06 -07: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 10:56:11 +01:00
|
|
|
*
|
2010-08-18 13:20:54 -07:00
|
|
|
*/
|
2014-08-15 01:21:56 +03:00
|
|
|
static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
|
2010-08-18 13:20:54 -07:00
|
|
|
{
|
2014-08-15 01:21:56 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2010-08-18 13:20:54 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
|
2014-08-15 01:21:56 +03:00
|
|
|
enum pipe pipe = crtc->pipe;
|
2010-10-03 00:33:06 -07:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = PIPECONF(cpu_transcoder);
|
2010-10-03 00:33:06 -07:00
|
|
|
|
|
|
|
|
/* Wait for the Pipe State to go off */
|
2010-10-03 10:56:11 +01:00
|
|
|
if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
|
|
|
|
|
100))
|
2012-07-09 09:51:57 +02:00
|
|
|
WARN(1, "pipe_off wait timed out\n");
|
2010-10-03 00:33:06 -07:00
|
|
|
} else {
|
|
|
|
|
/* Wait for the display line to settle */
|
2013-10-11 14:21:31 +03:00
|
|
|
if (wait_for(pipe_dsl_stopped(dev, pipe), 100))
|
2012-07-09 09:51:57 +02:00
|
|
|
WARN(1, "pipe_off wait timed out\n");
|
2010-10-03 00:33:06 -07: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2011-01-04 15:09:30 -08:00
|
|
|
static const char *state_string(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
return enabled ? "on" : "off";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Only for pre-ILK configs */
|
2013-06-16 21:42:39 +02:00
|
|
|
void assert_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, bool state)
|
2011-01-04 15:09:30 -08:00
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
bool cur_state;
|
|
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(DPLL(pipe));
|
2011-01-04 15:09:30 -08:00
|
|
|
cur_state = !!(val & DPLL_VCO_ENABLE);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2011-01-04 15:09:30 -08:00
|
|
|
"PLL state assertion failure (expected %s, current %s)\n",
|
|
|
|
|
state_string(state), state_string(cur_state));
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-27 15:12:22 +03:00
|
|
|
/* XXX: the dsi pll is shared between MIPI DSI ports */
|
|
|
|
|
static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
bool cur_state;
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2013-08-27 15:12:22 +03:00
|
|
|
val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2013-08-27 15:12:22 +03:00
|
|
|
|
|
|
|
|
cur_state = val & DSI_PLL_VCO_EN;
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2013-08-27 15:12:22 +03:00
|
|
|
"DSI PLL state assertion failure (expected %s, current %s)\n",
|
|
|
|
|
state_string(state), state_string(cur_state));
|
|
|
|
|
}
|
|
|
|
|
#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
|
|
|
|
|
#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
|
|
|
|
|
|
2013-06-16 21:42:39 +02:00
|
|
|
struct intel_shared_dpll *
|
2013-06-07 23:10:03 +02:00
|
|
|
intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->shared_dpll < 0)
|
2013-06-07 23:10:03 +02:00
|
|
|
return NULL;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
return &dev_priv->shared_dplls[crtc->config->shared_dpll];
|
2013-06-07 23:10:03 +02:00
|
|
|
}
|
|
|
|
|
|
2011-01-03 12:14:26 -08:00
|
|
|
/* For ILK+ */
|
2013-06-16 21:42:39 +02:00
|
|
|
void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_shared_dpll *pll,
|
|
|
|
|
bool state)
|
2011-01-03 12:14:26 -08:00
|
|
|
{
|
|
|
|
|
bool cur_state;
|
2013-06-05 13:34:16 +02:00
|
|
|
struct intel_dpll_hw_state hw_state;
|
2011-01-03 12:14:26 -08:00
|
|
|
|
2012-05-20 18:10:50 +01:00
|
|
|
if (WARN (!pll,
|
2013-06-05 13:34:12 +02:00
|
|
|
"asserting DPLL %s with no DPLL\n", state_string(state)))
|
2012-04-20 17:11:53 +01:00
|
|
|
return;
|
|
|
|
|
|
2013-06-05 13:34:16 +02:00
|
|
|
cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2013-06-05 13:34:16 +02:00
|
|
|
"%s assertion failure (expected %s, current %s)\n",
|
|
|
|
|
pll->name, state_string(state), state_string(cur_state));
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, bool state)
|
|
|
|
|
{
|
|
|
|
|
bool cur_state;
|
2012-10-24 16:06:19 -02:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
|
pipe);
|
2011-01-03 12:14:26 -08:00
|
|
|
|
2012-11-23 15:30:39 -02:00
|
|
|
if (HAS_DDI(dev_priv->dev)) {
|
|
|
|
|
/* DDI does not have a specific FDI_TX register */
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
|
2012-10-24 16:06:19 -02:00
|
|
|
cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
|
2012-05-09 15:37:18 -03:00
|
|
|
} else {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(FDI_TX_CTL(pipe));
|
2012-05-09 15:37:18 -03:00
|
|
|
cur_state = !!(val & FDI_TX_ENABLE);
|
|
|
|
|
}
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2011-01-03 12:14:26 -08:00
|
|
|
"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)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
bool cur_state;
|
|
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(FDI_RX_CTL(pipe));
|
2012-11-20 13:27:35 -02:00
|
|
|
cur_state = !!(val & FDI_RX_ENABLE);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2011-01-03 12:14:26 -08:00
|
|
|
"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)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
/* ILK FDI PLL is always enabled */
|
2014-02-07 19:12:47 +00:00
|
|
|
if (INTEL_INFO(dev_priv->dev)->gen == 5)
|
2011-01-03 12:14:26 -08:00
|
|
|
return;
|
|
|
|
|
|
2012-05-09 15:37:18 -03:00
|
|
|
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
|
2012-11-23 15:30:39 -02:00
|
|
|
if (HAS_DDI(dev_priv->dev))
|
2012-05-09 15:37:18 -03:00
|
|
|
return;
|
|
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(FDI_TX_CTL(pipe));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
2013-06-16 21:42:39 +02:00
|
|
|
void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, bool state)
|
2011-01-03 12:14:26 -08:00
|
|
|
{
|
|
|
|
|
u32 val;
|
2013-06-16 21:42:39 +02:00
|
|
|
bool cur_state;
|
2011-01-03 12:14:26 -08:00
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(FDI_RX_CTL(pipe));
|
2013-06-16 21:42:39 +02:00
|
|
|
cur_state = !!(val & FDI_RX_PLL_ENABLE);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2013-06-16 21:42:39 +02:00
|
|
|
"FDI RX PLL assertion failure (expected %s, current %s)\n",
|
|
|
|
|
state_string(state), state_string(cur_state));
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
2014-09-19 18:27:27 +02:00
|
|
|
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
2011-01-04 15:09:32 -08:00
|
|
|
{
|
2014-08-22 15:04:13 +03:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t pp_reg;
|
2011-01-04 15:09:32 -08:00
|
|
|
u32 val;
|
|
|
|
|
enum pipe panel_pipe = PIPE_A;
|
2011-08-25 15:37:45 +02:00
|
|
|
bool locked = true;
|
2011-01-04 15:09:32 -08:00
|
|
|
|
2014-08-22 15:04:13 +03:00
|
|
|
if (WARN_ON(HAS_DDI(dev)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (HAS_PCH_SPLIT(dev)) {
|
|
|
|
|
u32 port_sel;
|
|
|
|
|
|
2011-01-04 15:09:32 -08:00
|
|
|
pp_reg = PCH_PP_CONTROL;
|
2014-08-22 15:04:13 +03:00
|
|
|
port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
|
|
|
|
|
|
|
|
|
|
if (port_sel == PANEL_PORT_SELECT_LVDS &&
|
|
|
|
|
I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
|
|
|
|
|
panel_pipe = PIPE_B;
|
|
|
|
|
/* XXX: else fix for eDP */
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2014-08-22 15:04:13 +03:00
|
|
|
/* presumably write lock depends on pipe, not port select */
|
|
|
|
|
pp_reg = VLV_PIPE_PP_CONTROL(pipe);
|
|
|
|
|
panel_pipe = pipe;
|
2011-01-04 15:09:32 -08:00
|
|
|
} else {
|
|
|
|
|
pp_reg = PP_CONTROL;
|
2014-08-22 15:04:13 +03:00
|
|
|
if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
|
|
|
|
|
panel_pipe = PIPE_B;
|
2011-01-04 15:09:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = I915_READ(pp_reg);
|
|
|
|
|
if (!(val & PANEL_POWER_ON) ||
|
2014-08-21 15:06:25 +03:00
|
|
|
((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS))
|
2011-01-04 15:09:32 -08:00
|
|
|
locked = false;
|
|
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(panel_pipe == pipe && locked,
|
2011-01-04 15:09:32 -08:00
|
|
|
"panel assertion failure, pipe %c regs locked\n",
|
2011-02-07 12:26:52 -08:00
|
|
|
pipe_name(pipe));
|
2011-01-04 15:09:32 -08:00
|
|
|
}
|
|
|
|
|
|
2013-09-13 11:03:08 +03:00
|
|
|
static void assert_cursor(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, bool state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
bool cur_state;
|
|
|
|
|
|
2014-02-27 16:30:56 -03:00
|
|
|
if (IS_845G(dev) || IS_I865G(dev))
|
2015-09-22 19:47:51 +03:00
|
|
|
cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
|
2014-02-27 16:30:56 -03:00
|
|
|
else
|
2014-04-09 13:28:53 +03:00
|
|
|
cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
|
2013-09-13 11:03:08 +03:00
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2013-09-13 11:03:08 +03:00
|
|
|
"cursor on pipe %c assertion failure (expected %s, current %s)\n",
|
|
|
|
|
pipe_name(pipe), state_string(state), state_string(cur_state));
|
|
|
|
|
}
|
|
|
|
|
#define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
|
|
|
|
|
#define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
|
|
|
|
|
|
2011-12-13 13:19:38 -08:00
|
|
|
void assert_pipe(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, bool state)
|
2011-01-04 15:09:30 -08:00
|
|
|
{
|
2011-01-04 15:09:33 -08:00
|
|
|
bool cur_state;
|
2012-10-23 18:29:59 -02:00
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
|
|
pipe);
|
2011-01-04 15:09:30 -08:00
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
/* if we need the pipe quirk it must be always on */
|
|
|
|
|
if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
|
|
|
|
|
(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
|
2012-01-22 01:36:48 +01:00
|
|
|
state = true;
|
|
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv,
|
2013-05-03 12:15:36 -03:00
|
|
|
POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
|
2013-01-29 16:35:19 -02:00
|
|
|
cur_state = false;
|
|
|
|
|
} else {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(PIPECONF(cpu_transcoder));
|
2013-01-29 16:35:19 -02:00
|
|
|
cur_state = !!(val & PIPECONF_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2011-01-04 15:09:33 -08:00
|
|
|
"pipe %c assertion failure (expected %s, current %s)\n",
|
2011-02-07 12:26:52 -08:00
|
|
|
pipe_name(pipe), state_string(state), state_string(cur_state));
|
2011-01-04 15:09:30 -08:00
|
|
|
}
|
|
|
|
|
|
2012-01-16 23:01:13 +00:00
|
|
|
static void assert_plane(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum plane plane, bool state)
|
2011-01-04 15:09:30 -08:00
|
|
|
{
|
|
|
|
|
u32 val;
|
2012-01-16 23:01:13 +00:00
|
|
|
bool cur_state;
|
2011-01-04 15:09:30 -08:00
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(DSPCNTR(plane));
|
2012-01-16 23:01:13 +00:00
|
|
|
cur_state = !!(val & DISPLAY_PLANE_ENABLE);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(cur_state != state,
|
2012-01-16 23:01:13 +00:00
|
|
|
"plane %c assertion failure (expected %s, current %s)\n",
|
|
|
|
|
plane_name(plane), state_string(state), state_string(cur_state));
|
2011-01-04 15:09:30 -08:00
|
|
|
}
|
|
|
|
|
|
2012-01-16 23:01:13 +00: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-04 15:09:30 -08:00
|
|
|
static void assert_planes_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
|
|
|
|
{
|
2013-06-04 13:49:05 +03:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
2015-09-22 19:50:01 +03:00
|
|
|
int i;
|
2011-01-04 15:09:30 -08:00
|
|
|
|
2013-06-04 13:49:05 +03:00
|
|
|
/* Primary planes are fixed to pipes on gen4+ */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(DSPCNTR(pipe));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
|
2011-10-07 14:38:42 -04:00
|
|
|
"plane %c assertion failure, should be disabled but not\n",
|
|
|
|
|
plane_name(pipe));
|
2011-02-02 12:28:02 -08:00
|
|
|
return;
|
2011-10-07 14:38:42 -04:00
|
|
|
}
|
2011-02-02 12:28:02 -08:00
|
|
|
|
2011-01-04 15:09:30 -08:00
|
|
|
/* Need to check both planes against the pipe */
|
2014-08-18 13:49:10 +01:00
|
|
|
for_each_pipe(dev_priv, i) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(DSPCNTR(i));
|
|
|
|
|
enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
|
2011-01-04 15:09:30 -08:00
|
|
|
DISPPLANE_SEL_PIPE_SHIFT;
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
|
2011-02-07 12: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-04 15:09:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-28 09:55:38 -07:00
|
|
|
static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
|
|
|
|
{
|
2013-06-04 13:49:06 +03:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
2015-09-22 19:50:01 +03:00
|
|
|
int sprite;
|
2013-03-28 09:55:38 -07:00
|
|
|
|
2014-03-12 21:05:38 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
2015-02-28 14:54:09 +00:00
|
|
|
for_each_sprite(dev_priv, pipe, sprite) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(PLANE_CTL(pipe, sprite));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(val & PLANE_CTL_ENABLE,
|
2014-03-12 21:05:38 +00:00
|
|
|
"plane %d assertion failure, should be off on pipe %c but is still active\n",
|
|
|
|
|
sprite, pipe_name(pipe));
|
|
|
|
|
}
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2015-02-28 14:54:09 +00:00
|
|
|
for_each_sprite(dev_priv, pipe, sprite) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(SPCNTR(pipe, sprite));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(val & SP_ENABLE,
|
2013-06-04 13:49:06 +03:00
|
|
|
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
|
2014-03-03 17:31:47 +00:00
|
|
|
sprite_name(pipe, sprite), pipe_name(pipe));
|
2013-06-04 13:49:06 +03:00
|
|
|
}
|
|
|
|
|
} else if (INTEL_INFO(dev)->gen >= 7) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(SPRCTL(pipe));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(val & SPRITE_ENABLE,
|
2013-04-17 17:48:51 +03:00
|
|
|
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
|
2013-06-04 13:49:06 +03:00
|
|
|
plane_name(pipe), pipe_name(pipe));
|
|
|
|
|
} else if (INTEL_INFO(dev)->gen >= 5) {
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val = I915_READ(DVSCNTR(pipe));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(val & DVS_ENABLE,
|
2013-04-17 17:48:51 +03:00
|
|
|
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
|
2013-06-04 13:49:06 +03:00
|
|
|
plane_name(pipe), pipe_name(pipe));
|
2013-03-28 09:55:38 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-06 14:49:45 +03:00
|
|
|
static void assert_vblank_disabled(struct drm_crtc *crtc)
|
|
|
|
|
{
|
2014-12-15 13:56:32 -05:00
|
|
|
if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
|
2014-08-06 14:49:45 +03:00
|
|
|
drm_crtc_vblank_put(crtc);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-08 11:12:28 -02:00
|
|
|
static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
|
2011-01-04 15:09:34 -08:00
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
bool enabled;
|
|
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
|
2012-05-09 15:37:17 -03:00
|
|
|
|
2011-01-04 15:09:34 -08:00
|
|
|
val = I915_READ(PCH_DREF_CONTROL);
|
|
|
|
|
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
|
|
|
|
|
DREF_SUPERSPREAD_SOURCE_MASK));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
|
2011-01-04 15:09:34 -08:00
|
|
|
}
|
|
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
2011-01-04 15:09:34 -08:00
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
bool enabled;
|
|
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(PCH_TRANSCONF(pipe));
|
2011-01-04 15:09:34 -08:00
|
|
|
enabled = !!(val & TRANS_ENABLE);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(enabled,
|
2011-02-07 12:26:52 -08:00
|
|
|
"transcoder assertion failed, should be off on pipe %c but is still active\n",
|
|
|
|
|
pipe_name(pipe));
|
2011-01-04 15:09:34 -08:00
|
|
|
}
|
|
|
|
|
|
2011-08-06 10:39:45 -07:00
|
|
|
static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, u32 port_sel, u32 val)
|
2011-07-25 22:12:43 -07:00
|
|
|
{
|
|
|
|
|
if ((val & DP_PORT_EN) == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe));
|
2011-07-25 22:12:43 -07:00
|
|
|
if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
|
|
|
|
|
return false;
|
2014-04-09 13:28:21 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
|
|
|
|
|
if ((val & DP_PIPE_MASK_CHV) != DP_PIPE_SELECT_CHV(pipe))
|
|
|
|
|
return false;
|
2011-07-25 22:12:43 -07:00
|
|
|
} else {
|
|
|
|
|
if ((val & DP_PIPE_MASK) != (pipe << 30))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-06 10:35:34 -07:00
|
|
|
static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe, u32 val)
|
|
|
|
|
{
|
2013-02-19 16:21:46 -03:00
|
|
|
if ((val & SDVO_ENABLE) == 0)
|
2011-08-06 10:35:34 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev_priv->dev)) {
|
2013-02-19 16:21:46 -03:00
|
|
|
if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe))
|
2011-08-06 10:35:34 -07:00
|
|
|
return false;
|
2014-04-09 13:28:21 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
|
|
|
|
|
if ((val & SDVO_PIPE_SEL_MASK_CHV) != SDVO_PIPE_SEL_CHV(pipe))
|
|
|
|
|
return false;
|
2011-08-06 10:35:34 -07:00
|
|
|
} else {
|
2013-02-19 16:21:46 -03:00
|
|
|
if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe))
|
2011-08-06 10:35:34 -07: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-02 12:28:03 -08:00
|
|
|
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
enum pipe pipe, i915_reg_t reg,
|
|
|
|
|
u32 port_sel)
|
2011-02-02 12:28:03 -08:00
|
|
|
{
|
2011-02-07 13:46:40 -08:00
|
|
|
u32 val = I915_READ(reg);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
|
2011-02-02 12:28:03 -08:00
|
|
|
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_mmio_reg_offset(reg), pipe_name(pipe));
|
2012-06-05 11:03:40 +02:00
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
|
2012-09-10 21:58:29 +02:00
|
|
|
&& (val & DP_PIPEB_SELECT),
|
2012-06-05 11:03:40 +02:00
|
|
|
"IBX PCH dp port still using transcoder B\n");
|
2011-02-02 12:28:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
enum pipe pipe, i915_reg_t reg)
|
2011-02-02 12:28:03 -08:00
|
|
|
{
|
2011-02-07 13:46:40 -08:00
|
|
|
u32 val = I915_READ(reg);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
|
2011-10-07 14:38:43 -04:00
|
|
|
"PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_mmio_reg_offset(reg), pipe_name(pipe));
|
2012-06-05 11:03:40 +02:00
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
|
2012-09-10 21:58:29 +02:00
|
|
|
&& (val & SDVO_PIPE_B_SELECT),
|
2012-06-05 11:03:40 +02:00
|
|
|
"IBX PCH hdmi port still using transcoder B\n");
|
2011-02-02 12:28:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
|
2011-07-25 22:12:43 -07: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-02 12:28:03 -08:00
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(PCH_ADPA);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val),
|
2011-02-02 12:28:03 -08:00
|
|
|
"PCH VGA enabled on transcoder %c, should be disabled\n",
|
2011-02-07 12:26:52 -08:00
|
|
|
pipe_name(pipe));
|
2011-02-02 12:28:03 -08:00
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(PCH_LVDS);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val),
|
2011-02-02 12:28:03 -08:00
|
|
|
"PCH LVDS enabled on transcoder %c, should be disabled\n",
|
2011-02-07 12:26:52 -08:00
|
|
|
pipe_name(pipe));
|
2011-02-02 12: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-18 19:00:27 -03: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-02 12:28:03 -08:00
|
|
|
}
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
static void vlv_enable_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config)
|
2013-06-06 00:52:17 +02:00
|
|
|
{
|
2013-07-11 22:13:42 +02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = DPLL(crtc->pipe);
|
2014-10-28 13:20:22 +02:00
|
|
|
u32 dpll = pipe_config->dpll_hw_state.dpll;
|
2013-06-06 00:52:17 +02:00
|
|
|
|
2013-07-11 22:13:42 +02:00
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-06-06 00:52:17 +02:00
|
|
|
|
|
|
|
|
/* PLL is protected by panel, make sure we can write it */
|
2014-08-22 15:06:35 +03:00
|
|
|
if (IS_MOBILE(dev_priv->dev))
|
2013-07-11 22:13:42 +02:00
|
|
|
assert_panel_unlocked(dev_priv, crtc->pipe);
|
2013-06-06 00:52:17 +02:00
|
|
|
|
2013-07-11 22:13:42 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150);
|
|
|
|
|
|
|
|
|
|
if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
|
|
|
|
|
DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe);
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
I915_WRITE(DPLL_MD(crtc->pipe), pipe_config->dpll_hw_state.dpll_md);
|
2013-07-11 22:13:42 +02:00
|
|
|
POSTING_READ(DPLL_MD(crtc->pipe));
|
2013-06-06 00:52:17 +02:00
|
|
|
|
|
|
|
|
/* We do this three times for luck */
|
2013-07-11 22:13:42 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2013-06-06 00:52:17 +02:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
2013-07-11 22:13:42 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2013-06-06 00:52:17 +02:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
2013-07-11 22:13:42 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2013-06-06 00:52:17 +02:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
static void chv_enable_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config)
|
2014-05-02 14:27:47 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = crtc->pipe;
|
|
|
|
|
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
|
|
|
|
u32 tmp;
|
|
|
|
|
|
|
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2014-05-02 14:27:47 +03:00
|
|
|
|
|
|
|
|
/* Enable back the 10bit clock to display controller */
|
|
|
|
|
tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
|
|
|
|
tmp |= DPIO_DCLKP_EN;
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp);
|
|
|
|
|
|
2015-05-26 20:42:31 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
|
2014-05-02 14:27:47 +03:00
|
|
|
/*
|
|
|
|
|
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
|
|
|
|
|
*/
|
|
|
|
|
udelay(1);
|
|
|
|
|
|
|
|
|
|
/* Enable PLL */
|
2014-10-28 13:20:22 +02:00
|
|
|
I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
|
2014-05-02 14:27:47 +03:00
|
|
|
|
|
|
|
|
/* Check PLL is locked */
|
2014-04-09 13:28:57 +03:00
|
|
|
if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
|
2014-05-02 14:27:47 +03:00
|
|
|
DRM_ERROR("PLL %d failed to lock\n", pipe);
|
|
|
|
|
|
2014-04-09 13:28:57 +03:00
|
|
|
/* not sure when this should be written */
|
2014-10-28 13:20:22 +02:00
|
|
|
I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md);
|
2014-04-09 13:28:57 +03:00
|
|
|
POSTING_READ(DPLL_MD(pipe));
|
2014-05-02 14:27:47 +03:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 21:52:42 +03:00
|
|
|
static int intel_num_dvo_pipes(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc)
|
2015-06-01 12:50:10 +02:00
|
|
|
count += crtc->base.state->active &&
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO);
|
2014-09-05 21:52:42 +03:00
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-16 21:24:16 +02:00
|
|
|
static void i9xx_enable_pll(struct intel_crtc *crtc)
|
2011-01-04 15:09:33 -08:00
|
|
|
{
|
2013-06-16 21:24:16 +02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = DPLL(crtc->pipe);
|
2015-01-15 14:55:25 +02:00
|
|
|
u32 dpll = crtc->config->dpll_hw_state.dpll;
|
2011-01-04 15:09:33 -08:00
|
|
|
|
2013-06-16 21:24:16 +02:00
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-04-11 16:29:09 +02:00
|
|
|
|
2011-01-04 15:09:33 -08:00
|
|
|
/* No really, not for ILK+ */
|
2014-02-07 19:12:47 +00:00
|
|
|
BUG_ON(INTEL_INFO(dev)->gen >= 5);
|
2011-01-04 15:09:33 -08:00
|
|
|
|
|
|
|
|
/* PLL is protected by panel, make sure we can write it */
|
2013-06-16 21:24:16 +02:00
|
|
|
if (IS_MOBILE(dev) && !IS_I830(dev))
|
|
|
|
|
assert_panel_unlocked(dev_priv, crtc->pipe);
|
2011-01-04 15:09:33 -08:00
|
|
|
|
2014-09-05 21:52:42 +03:00
|
|
|
/* Enable DVO 2x clock on both PLLs if necessary */
|
|
|
|
|
if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) {
|
|
|
|
|
/*
|
|
|
|
|
* It appears to be important that we don't enable this
|
|
|
|
|
* for the current pipe before otherwise configuring the
|
|
|
|
|
* PLL. No idea how this should be handled if multiple
|
|
|
|
|
* DVO outputs are enabled simultaneosly.
|
|
|
|
|
*/
|
|
|
|
|
dpll |= DPLL_DVO_2X_MODE;
|
|
|
|
|
I915_WRITE(DPLL(!crtc->pipe),
|
|
|
|
|
I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
|
|
|
|
|
}
|
2013-06-16 21:24:16 +02:00
|
|
|
|
2015-10-07 22:08:25 +03:00
|
|
|
/*
|
|
|
|
|
* Apparently we need to have VGA mode enabled prior to changing
|
|
|
|
|
* the P1/P2 dividers. Otherwise the DPLL will keep using the old
|
|
|
|
|
* dividers, even though the register value does change.
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(reg, 0);
|
|
|
|
|
|
2015-10-07 22:08:24 +03:00
|
|
|
I915_WRITE(reg, dpll);
|
|
|
|
|
|
2013-06-16 21:24:16 +02:00
|
|
|
/* Wait for the clocks to stabilize. */
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150);
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
I915_WRITE(DPLL_MD(crtc->pipe),
|
2015-01-15 14:55:25 +02:00
|
|
|
crtc->config->dpll_hw_state.dpll_md);
|
2013-06-16 21:24:16 +02: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(reg, dpll);
|
|
|
|
|
}
|
2011-01-04 15:09:33 -08:00
|
|
|
|
|
|
|
|
/* We do this three times for luck */
|
2013-06-16 21:24:16 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2011-01-04 15:09:33 -08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
2013-06-16 21:24:16 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2011-01-04 15:09:33 -08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
2013-06-16 21:24:16 +02:00
|
|
|
I915_WRITE(reg, dpll);
|
2011-01-04 15:09:33 -08:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150); /* wait for warmup */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2013-06-05 13:34:33 +02:00
|
|
|
* i9xx_disable_pll - disable a PLL
|
2011-01-04 15:09:33 -08:00
|
|
|
* @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.
|
|
|
|
|
*/
|
2014-09-05 21:52:42 +03:00
|
|
|
static void i9xx_disable_pll(struct intel_crtc *crtc)
|
2011-01-04 15:09:33 -08:00
|
|
|
{
|
2014-09-05 21:52:42 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
|
|
|
|
|
|
|
|
|
/* Disable DVO 2x clock on both PLLs if necessary */
|
|
|
|
|
if (IS_I830(dev) &&
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO) &&
|
2015-06-01 12:50:10 +02:00
|
|
|
!intel_num_dvo_pipes(dev)) {
|
2014-09-05 21:52:42 +03:00
|
|
|
I915_WRITE(DPLL(PIPE_B),
|
|
|
|
|
I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
|
|
|
|
|
I915_WRITE(DPLL(PIPE_A),
|
|
|
|
|
I915_READ(DPLL(PIPE_A)) & ~DPLL_DVO_2X_MODE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
/* Don't disable pipe or pipe PLLs if needed */
|
|
|
|
|
if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
|
|
|
|
|
(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
|
2011-01-04 15:09:33 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Make sure the pipe isn't still relying on us */
|
|
|
|
|
assert_pipe_disabled(dev_priv, pipe);
|
|
|
|
|
|
2015-06-29 15:25:48 +03:00
|
|
|
I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);
|
2013-06-05 13:34:33 +02:00
|
|
|
POSTING_READ(DPLL(pipe));
|
2011-01-04 15:09:33 -08:00
|
|
|
}
|
|
|
|
|
|
2013-10-01 10:41:38 -07:00
|
|
|
static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
|
|
{
|
2015-06-29 15:25:48 +03:00
|
|
|
u32 val;
|
2013-10-01 10:41:38 -07:00
|
|
|
|
|
|
|
|
/* Make sure the pipe isn't still relying on us */
|
|
|
|
|
assert_pipe_disabled(dev_priv, pipe);
|
|
|
|
|
|
2014-01-09 17:08:16 +02:00
|
|
|
/*
|
|
|
|
|
* Leave integrated clock source and reference clock enabled for pipe B.
|
|
|
|
|
* The latter is needed for VGA hotplug / manual detection.
|
|
|
|
|
*/
|
2015-06-29 15:25:48 +03:00
|
|
|
val = DPLL_VGA_MODE_DIS;
|
2013-10-01 10:41:38 -07:00
|
|
|
if (pipe == PIPE_B)
|
2015-06-29 15:25:49 +03:00
|
|
|
val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV;
|
2013-10-01 10:41:38 -07:00
|
|
|
I915_WRITE(DPLL(pipe), val);
|
|
|
|
|
POSTING_READ(DPLL(pipe));
|
2014-04-09 13:28:17 +03:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|
|
|
|
{
|
2014-04-09 13:28:59 +03:00
|
|
|
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
2014-04-09 13:28:17 +03:00
|
|
|
u32 val;
|
|
|
|
|
|
2014-04-09 13:28:57 +03:00
|
|
|
/* Make sure the pipe isn't still relying on us */
|
|
|
|
|
assert_pipe_disabled(dev_priv, pipe);
|
2014-04-09 13:28:17 +03:00
|
|
|
|
2014-04-09 13:28:57 +03:00
|
|
|
/* Set PLL en = 0 */
|
2015-06-29 15:25:49 +03:00
|
|
|
val = DPLL_SSC_REF_CLK_CHV |
|
|
|
|
|
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
|
2014-04-09 13:28:57 +03:00
|
|
|
if (pipe != PIPE_A)
|
|
|
|
|
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
|
|
|
|
I915_WRITE(DPLL(pipe), val);
|
|
|
|
|
POSTING_READ(DPLL(pipe));
|
2014-04-09 13:28:59 +03:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2014-04-09 13:28:59 +03:00
|
|
|
|
|
|
|
|
/* Disable 10bit clock to display controller */
|
|
|
|
|
val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
|
|
|
|
val &= ~DPIO_DCLKP_EN;
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2013-10-01 10:41:38 -07:00
|
|
|
}
|
|
|
|
|
|
2013-11-06 14:36:35 +08:00
|
|
|
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
|
2015-04-10 18:21:31 +03:00
|
|
|
struct intel_digital_port *dport,
|
|
|
|
|
unsigned int expected_mask)
|
2013-04-18 14:51:36 -07:00
|
|
|
{
|
|
|
|
|
u32 port_mask;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t dpll_reg;
|
2013-04-18 14:51:36 -07:00
|
|
|
|
2013-11-06 14:36:35 +08:00
|
|
|
switch (dport->port) {
|
|
|
|
|
case PORT_B:
|
2013-04-18 14:51:36 -07:00
|
|
|
port_mask = DPLL_PORTB_READY_MASK;
|
2014-04-09 13:28:15 +03:00
|
|
|
dpll_reg = DPLL(0);
|
2013-11-06 14:36:35 +08:00
|
|
|
break;
|
|
|
|
|
case PORT_C:
|
2013-04-18 14:51:36 -07:00
|
|
|
port_mask = DPLL_PORTC_READY_MASK;
|
2014-04-09 13:28:15 +03:00
|
|
|
dpll_reg = DPLL(0);
|
2015-04-10 18:21:31 +03:00
|
|
|
expected_mask <<= 4;
|
2014-04-09 13:28:15 +03:00
|
|
|
break;
|
|
|
|
|
case PORT_D:
|
|
|
|
|
port_mask = DPLL_PORTD_READY_MASK;
|
|
|
|
|
dpll_reg = DPIO_PHY_STATUS;
|
2013-11-06 14:36:35 +08:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BUG();
|
|
|
|
|
}
|
2013-04-18 14:51:36 -07:00
|
|
|
|
2015-04-10 18:21:31 +03:00
|
|
|
if (wait_for((I915_READ(dpll_reg) & port_mask) == expected_mask, 1000))
|
|
|
|
|
WARN(1, "timed out waiting for port %c ready: got 0x%x, expected 0x%x\n",
|
|
|
|
|
port_name(dport->port), I915_READ(dpll_reg) & port_mask, expected_mask);
|
2013-04-18 14:51:36 -07:00
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:55:13 +02:00
|
|
|
static void intel_prepare_shared_dpll(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
|
|
|
|
|
|
2014-05-28 16:16:42 +01:00
|
|
|
if (WARN_ON(pll == NULL))
|
|
|
|
|
return;
|
|
|
|
|
|
2014-10-29 11:32:32 +02:00
|
|
|
WARN_ON(!pll->config.crtc_mask);
|
2014-04-24 23:55:13 +02:00
|
|
|
if (pll->active == 0) {
|
|
|
|
|
DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
|
|
|
|
|
WARN_ON(pll->on);
|
|
|
|
|
assert_shared_dpll_disabled(dev_priv, pll);
|
|
|
|
|
|
|
|
|
|
pll->mode_set(dev_priv, pll);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 15:09:34 -08:00
|
|
|
/**
|
2014-04-24 23:55:14 +02:00
|
|
|
* intel_enable_shared_dpll - enable PCH PLL
|
2011-01-04 15: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.
|
|
|
|
|
*/
|
2014-04-24 23:55:14 +02:00
|
|
|
static void intel_enable_shared_dpll(struct intel_crtc *crtc)
|
2011-01-04 15:09:34 -08:00
|
|
|
{
|
2014-02-07 19:12:47 +00:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-07 23:10:03 +02:00
|
|
|
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
|
2011-01-04 15:09:34 -08:00
|
|
|
|
2013-06-05 13:34:19 +02:00
|
|
|
if (WARN_ON(pll == NULL))
|
2012-05-13 20:16:12 +01:00
|
|
|
return;
|
|
|
|
|
|
2014-10-29 11:32:32 +02:00
|
|
|
if (WARN_ON(pll->config.crtc_mask == 0))
|
2012-05-13 20:16:12 +01:00
|
|
|
return;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2014-07-29 18:06:17 +01:00
|
|
|
DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
|
2013-06-05 13:34:12 +02:00
|
|
|
pll->name, pll->active, pll->on,
|
2013-06-07 23:10:03 +02:00
|
|
|
crtc->base.base.id);
|
2011-01-04 15:09:34 -08:00
|
|
|
|
2013-06-05 13:34:03 +02:00
|
|
|
if (pll->active++) {
|
|
|
|
|
WARN_ON(!pll->on);
|
2013-06-05 13:34:15 +02:00
|
|
|
assert_shared_dpll_enabled(dev_priv, pll);
|
2012-04-20 17:11:53 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2013-06-10 17:28:22 +02:00
|
|
|
WARN_ON(pll->on);
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2014-07-04 11:27:38 -03:00
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
|
|
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_KMS("enabling %s\n", pll->name);
|
2013-06-05 13:34:14 +02:00
|
|
|
pll->enable(dev_priv, pll);
|
2012-04-20 17:11:53 +01:00
|
|
|
pll->on = true;
|
2011-01-04 15:09:34 -08:00
|
|
|
}
|
|
|
|
|
|
2014-08-09 23:00:56 +01:00
|
|
|
static void intel_disable_shared_dpll(struct intel_crtc *crtc)
|
2011-01-04 15:09:34 -08:00
|
|
|
{
|
2014-02-07 19:12:47 +00:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-07 23:10:03 +02:00
|
|
|
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
|
2011-09-02 12:52:11 -07:00
|
|
|
|
2011-01-04 15:09:34 -08:00
|
|
|
/* PCH only available on ILK+ */
|
2015-08-03 13:09:11 -07:00
|
|
|
if (INTEL_INFO(dev)->gen < 5)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-06-15 12:33:53 +02:00
|
|
|
if (pll == NULL)
|
|
|
|
|
return;
|
2011-01-04 15:09:34 -08:00
|
|
|
|
2015-06-15 12:33:53 +02:00
|
|
|
if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
|
2012-05-13 20:16:12 +01:00
|
|
|
return;
|
2011-11-15 10:28:53 -08:00
|
|
|
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
|
|
|
|
|
pll->name, pll->active, pll->on,
|
2013-06-07 23:10:03 +02:00
|
|
|
crtc->base.base.id);
|
2011-11-15 10:28:53 -08:00
|
|
|
|
2012-05-13 20:16:12 +01:00
|
|
|
if (WARN_ON(pll->active == 0)) {
|
2013-06-05 13:34:15 +02:00
|
|
|
assert_shared_dpll_disabled(dev_priv, pll);
|
2012-05-13 20:16:12 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:15 +02:00
|
|
|
assert_shared_dpll_enabled(dev_priv, pll);
|
2013-06-10 17:28:22 +02:00
|
|
|
WARN_ON(!pll->on);
|
2013-06-05 13:34:03 +02:00
|
|
|
if (--pll->active)
|
2011-11-15 10:28:53 -08:00
|
|
|
return;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_KMS("disabling %s\n", pll->name);
|
2013-06-05 13:34:14 +02:00
|
|
|
pll->disable(dev_priv, pll);
|
2012-04-20 17:11:53 +01:00
|
|
|
pll->on = false;
|
2014-07-04 11:27:38 -03:00
|
|
|
|
|
|
|
|
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
|
2011-01-04 15:09:34 -08:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 18:12:42 -02:00
|
|
|
static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
2011-01-03 12: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 09:15:30 +01:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
2012-02-14 17:07:09 -02:00
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
2013-06-07 23:10:03 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
uint32_t val, pipeconf_val;
|
2011-01-03 12:14:26 -08:00
|
|
|
|
|
|
|
|
/* PCH only available on ILK+ */
|
2014-09-03 14:09:53 +03:00
|
|
|
BUG_ON(!HAS_PCH_SPLIT(dev));
|
2011-01-03 12:14:26 -08:00
|
|
|
|
|
|
|
|
/* Make sure PCH DPLL is enabled */
|
2013-06-05 13:34:06 +02:00
|
|
|
assert_shared_dpll_enabled(dev_priv,
|
2013-06-05 13:34:15 +02:00
|
|
|
intel_crtc_to_shared_dpll(intel_crtc));
|
2011-01-03 12: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 09:15:30 +01: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-09 15:37:19 -03: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 09:15:30 +01:00
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
reg = PCH_TRANSCONF(pipe);
|
2011-01-03 12:14:26 -08:00
|
|
|
val = I915_READ(reg);
|
2012-02-03 17:47:15 -02:00
|
|
|
pipeconf_val = I915_READ(PIPECONF(pipe));
|
2011-06-24 12:19:20 -07:00
|
|
|
|
|
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
|
|
/*
|
2015-05-05 17:06:22 +03:00
|
|
|
* Make the BPC in transcoder be consistent with
|
|
|
|
|
* that in pipeconf reg. For HDMI we must use 8bpc
|
|
|
|
|
* here for both 8bpc and 12bpc.
|
2011-06-24 12:19:20 -07:00
|
|
|
*/
|
2012-12-17 11:21:38 +01:00
|
|
|
val &= ~PIPECONF_BPC_MASK;
|
2015-05-05 17:06:22 +03:00
|
|
|
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_HDMI))
|
|
|
|
|
val |= PIPECONF_8BPC;
|
|
|
|
|
else
|
|
|
|
|
val |= pipeconf_val & PIPECONF_BPC_MASK;
|
2011-06-24 12:19:20 -07:00
|
|
|
}
|
2012-02-03 17:47:15 -02:00
|
|
|
|
|
|
|
|
val &= ~TRANS_INTERLACE_MASK;
|
|
|
|
|
if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
|
2012-02-14 17:07:09 -02:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev) &&
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
|
2012-02-14 17:07:09 -02:00
|
|
|
val |= TRANS_LEGACY_INTERLACED_ILK;
|
|
|
|
|
else
|
|
|
|
|
val |= TRANS_INTERLACED;
|
2012-02-03 17:47:15 -02:00
|
|
|
else
|
|
|
|
|
val |= TRANS_PROGRESSIVE;
|
|
|
|
|
|
2011-01-03 12:14:26 -08:00
|
|
|
I915_WRITE(reg, val | TRANS_ENABLE);
|
|
|
|
|
if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
|
2013-04-17 17:48:50 +03:00
|
|
|
DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 18:12:43 -02:00
|
|
|
static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
2012-10-31 18:12:47 -02:00
|
|
|
enum transcoder cpu_transcoder)
|
2011-01-03 12:14:26 -08:00
|
|
|
{
|
2012-10-31 18:12:43 -02:00
|
|
|
u32 val, pipeconf_val;
|
|
|
|
|
|
|
|
|
|
/* PCH only available on ILK+ */
|
2014-09-03 14:09:53 +03:00
|
|
|
BUG_ON(!HAS_PCH_SPLIT(dev_priv->dev));
|
2012-10-31 18:12:43 -02:00
|
|
|
|
|
|
|
|
/* FDI must be feeding us bits for PCH ports */
|
2012-11-29 22:18:51 +01:00
|
|
|
assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
|
2012-10-31 18:12:47 -02:00
|
|
|
assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
|
2012-10-31 18:12:43 -02:00
|
|
|
|
2012-10-31 18:12:52 -02:00
|
|
|
/* Workaround: set timing override bit. */
|
2015-09-18 20:03:31 +03:00
|
|
|
val = I915_READ(TRANS_CHICKEN2(PIPE_A));
|
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 09:15:30 +01:00
|
|
|
val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
|
2015-09-18 20:03:31 +03:00
|
|
|
I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
|
2012-10-31 18:12:52 -02:00
|
|
|
|
2012-10-31 18:12:49 -02:00
|
|
|
val = TRANS_ENABLE;
|
2012-10-31 18:12:47 -02:00
|
|
|
pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
|
2012-10-31 18:12:43 -02:00
|
|
|
|
2012-10-31 18:12:48 -02:00
|
|
|
if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
|
|
|
|
|
PIPECONF_INTERLACED_ILK)
|
2012-10-31 18:12:45 -02:00
|
|
|
val |= TRANS_INTERLACED;
|
2012-10-31 18:12:43 -02:00
|
|
|
else
|
|
|
|
|
val |= TRANS_PROGRESSIVE;
|
|
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
I915_WRITE(LPT_TRANSCONF, val);
|
|
|
|
|
if (wait_for(I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE, 100))
|
2012-10-31 18:12:47 -02:00
|
|
|
DRM_ERROR("Failed to enable PCH transcoder\n");
|
2012-10-31 18:12:43 -02:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 18:12:42 -02:00
|
|
|
static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum pipe pipe)
|
2011-01-03 12: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 09:15:30 +01:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
uint32_t val;
|
2011-01-03 12: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-02 12:28:03 -08:00
|
|
|
/* Ports must be off as well */
|
|
|
|
|
assert_pch_ports_disabled(dev_priv, pipe);
|
|
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
reg = PCH_TRANSCONF(pipe);
|
2011-01-03 12: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 17:48:50 +03: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 09:15:30 +01:00
|
|
|
|
2015-10-29 21:25:56 +02:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
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 09:15:30 +01:00
|
|
|
/* 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-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 18:12:55 -02:00
|
|
|
static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
|
2012-10-31 18:12:43 -02:00
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
val = I915_READ(LPT_TRANSCONF);
|
2012-10-31 18:12:43 -02:00
|
|
|
val &= ~TRANS_ENABLE;
|
2013-05-03 11:49:46 +02:00
|
|
|
I915_WRITE(LPT_TRANSCONF, val);
|
2012-10-31 18:12:43 -02:00
|
|
|
/* wait for PCH transcoder off, transcoder state */
|
2013-05-03 11:49:46 +02:00
|
|
|
if (wait_for((I915_READ(LPT_TRANSCONF) & TRANS_STATE_ENABLE) == 0, 50))
|
2012-10-31 18:12:51 -02:00
|
|
|
DRM_ERROR("Failed to disable PCH transcoder\n");
|
2012-10-31 18:12:52 -02:00
|
|
|
|
|
|
|
|
/* Workaround: clear timing override bit. */
|
2015-09-18 20:03:31 +03:00
|
|
|
val = I915_READ(TRANS_CHICKEN2(PIPE_A));
|
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 09:15:30 +01:00
|
|
|
val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
|
2015-09-18 20:03:31 +03:00
|
|
|
I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
2011-01-04 15:09:30 -08:00
|
|
|
/**
|
2011-01-28 13:54:53 +00:00
|
|
|
* intel_enable_pipe - enable a pipe, asserting requirements
|
2014-01-17 13:51:09 -02:00
|
|
|
* @crtc: crtc responsible for the pipe
|
2011-01-04 15:09:30 -08:00
|
|
|
*
|
2014-01-17 13:51:09 -02:00
|
|
|
* Enable @crtc's pipe, making sure that various hardware specific requirements
|
2011-01-04 15:09:30 -08:00
|
|
|
* are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
|
|
|
|
|
*/
|
2014-01-17 13:51:12 -02:00
|
|
|
static void intel_enable_pipe(struct intel_crtc *crtc)
|
2011-01-04 15:09:30 -08:00
|
|
|
{
|
2014-01-17 13:51:09 -02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
2015-10-29 21:25:50 +02:00
|
|
|
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
|
2012-11-29 22:18:51 +01:00
|
|
|
enum pipe pch_transcoder;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
2011-01-04 15:09:30 -08:00
|
|
|
u32 val;
|
|
|
|
|
|
2015-06-24 21:59:35 +03:00
|
|
|
DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
|
|
|
|
|
|
2013-04-11 16:29:09 +02:00
|
|
|
assert_planes_disabled(dev_priv, pipe);
|
2013-09-13 11:03:08 +03:00
|
|
|
assert_cursor_disabled(dev_priv, pipe);
|
2013-04-11 16:29:09 +02:00
|
|
|
assert_sprites_disabled(dev_priv, pipe);
|
|
|
|
|
|
2012-12-06 11:12:38 -02:00
|
|
|
if (HAS_PCH_LPT(dev_priv->dev))
|
2012-11-20 13:27:37 -02:00
|
|
|
pch_transcoder = TRANSCODER_A;
|
|
|
|
|
else
|
|
|
|
|
pch_transcoder = pipe;
|
|
|
|
|
|
2011-01-04 15: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.
|
|
|
|
|
*/
|
2015-01-16 00:55:16 -08:00
|
|
|
if (HAS_GMCH_DISPLAY(dev_priv->dev))
|
2015-11-27 12:21:46 +02:00
|
|
|
if (crtc->config->has_dsi_encoder)
|
2013-08-27 15:12:22 +03:00
|
|
|
assert_dsi_pll_enabled(dev_priv);
|
|
|
|
|
else
|
|
|
|
|
assert_pll_enabled(dev_priv, pipe);
|
2011-01-03 12:14:26 -08:00
|
|
|
else {
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->has_pch_encoder) {
|
2011-01-03 12:14:26 -08:00
|
|
|
/* if driving the PCH, we need FDI enabled */
|
2012-11-20 13:27:37 -02:00
|
|
|
assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
|
2012-11-29 22:18:51 +01:00
|
|
|
assert_fdi_tx_pll_enabled(dev_priv,
|
|
|
|
|
(enum pipe) cpu_transcoder);
|
2011-01-03 12:14:26 -08:00
|
|
|
}
|
|
|
|
|
/* FIXME: assert CPU port conditions for SNB+ */
|
|
|
|
|
}
|
2011-01-04 15:09:30 -08:00
|
|
|
|
2012-10-23 18:29:59 -02:00
|
|
|
reg = PIPECONF(cpu_transcoder);
|
2011-01-04 15:09:30 -08:00
|
|
|
val = I915_READ(reg);
|
2014-01-17 13:51:13 -02:00
|
|
|
if (val & PIPECONF_ENABLE) {
|
2014-08-15 01:22:07 +03:00
|
|
|
WARN_ON(!((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
|
|
|
|
|
(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)));
|
2011-03-17 07:18:29 +00:00
|
|
|
return;
|
2014-01-17 13:51:13 -02:00
|
|
|
}
|
2011-03-17 07:18:29 +00:00
|
|
|
|
|
|
|
|
I915_WRITE(reg, val | PIPECONF_ENABLE);
|
2013-12-19 19:12:29 -02:00
|
|
|
POSTING_READ(reg);
|
2011-01-04 15:09:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-01-28 13:54:53 +00:00
|
|
|
* intel_disable_pipe - disable a pipe, asserting requirements
|
2014-08-15 01:21:56 +03:00
|
|
|
* @crtc: crtc whose pipes is to be disabled
|
2011-01-04 15:09:30 -08:00
|
|
|
*
|
2014-08-15 01:21:56 +03:00
|
|
|
* Disable the pipe of @crtc, making sure that various hardware
|
|
|
|
|
* specific requirements are met, if applicable, e.g. plane
|
|
|
|
|
* disabled, panel fitter off, etc.
|
2011-01-04 15:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Will wait until the pipe has shut down before returning.
|
|
|
|
|
*/
|
2014-08-15 01:21:56 +03:00
|
|
|
static void intel_disable_pipe(struct intel_crtc *crtc)
|
2011-01-04 15:09:30 -08:00
|
|
|
{
|
2014-08-15 01:21:56 +03:00
|
|
|
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
|
2014-08-15 01:21:56 +03:00
|
|
|
enum pipe pipe = crtc->pipe;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
2011-01-04 15:09:30 -08:00
|
|
|
u32 val;
|
|
|
|
|
|
2015-06-24 21:59:35 +03:00
|
|
|
DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe));
|
|
|
|
|
|
2011-01-04 15:09:30 -08:00
|
|
|
/*
|
|
|
|
|
* 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-09-13 11:03:08 +03:00
|
|
|
assert_cursor_disabled(dev_priv, pipe);
|
2013-03-28 09:55:38 -07:00
|
|
|
assert_sprites_disabled(dev_priv, pipe);
|
2011-01-04 15:09:30 -08:00
|
|
|
|
2012-10-23 18:29:59 -02:00
|
|
|
reg = PIPECONF(cpu_transcoder);
|
2011-01-04 15:09:30 -08:00
|
|
|
val = I915_READ(reg);
|
2011-03-17 07:18:29 +00:00
|
|
|
if ((val & PIPECONF_ENABLE) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-08-15 01:21:57 +03:00
|
|
|
/*
|
|
|
|
|
* Double wide has implications for planes
|
|
|
|
|
* so best keep it disabled when not needed.
|
|
|
|
|
*/
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->double_wide)
|
2014-08-15 01:21:57 +03:00
|
|
|
val &= ~PIPECONF_DOUBLE_WIDE;
|
|
|
|
|
|
|
|
|
|
/* Don't disable pipe or pipe PLLs if needed */
|
2014-08-15 01:22:07 +03:00
|
|
|
if (!(pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) &&
|
|
|
|
|
!(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
|
2014-08-15 01:21:57 +03:00
|
|
|
val &= ~PIPECONF_ENABLE;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(reg, val);
|
|
|
|
|
if ((val & PIPECONF_ENABLE) == 0)
|
|
|
|
|
intel_wait_for_pipe_off(crtc);
|
2011-01-04 15:09:30 -08:00
|
|
|
}
|
|
|
|
|
|
2013-03-05 14:52:39 +00: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-23 11:10:36 +00:00
|
|
|
unsigned int
|
2015-03-23 11:10:32 +00:00
|
|
|
intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
|
2015-09-21 10:45:32 +01:00
|
|
|
uint64_t fb_format_modifier, unsigned int plane)
|
2014-02-07 12:10:35 -08:00
|
|
|
{
|
2015-03-23 11:10:32 +00:00
|
|
|
unsigned int tile_height;
|
|
|
|
|
uint32_t pixel_bytes;
|
2014-02-07 12:10:35 -08:00
|
|
|
|
2015-02-27 11:15:19 +00:00
|
|
|
switch (fb_format_modifier) {
|
|
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
|
|
tile_height = 1;
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
|
|
tile_height = IS_GEN2(dev) ? 16 : 8;
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
tile_height = 32;
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
2015-09-21 10:45:32 +01:00
|
|
|
pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
|
2015-03-23 11:10:32 +00:00
|
|
|
switch (pixel_bytes) {
|
2015-02-27 11:15:19 +00:00
|
|
|
default:
|
2015-03-23 11:10:32 +00:00
|
|
|
case 1:
|
2015-02-27 11:15:19 +00:00
|
|
|
tile_height = 64;
|
|
|
|
|
break;
|
2015-03-23 11:10:32 +00:00
|
|
|
case 2:
|
|
|
|
|
case 4:
|
2015-02-27 11:15:19 +00:00
|
|
|
tile_height = 32;
|
|
|
|
|
break;
|
2015-03-23 11:10:32 +00:00
|
|
|
case 8:
|
2015-02-27 11:15:19 +00:00
|
|
|
tile_height = 16;
|
|
|
|
|
break;
|
2015-03-23 11:10:32 +00:00
|
|
|
case 16:
|
2015-02-27 11:15:19 +00:00
|
|
|
WARN_ONCE(1,
|
|
|
|
|
"128-bit pixels are not supported for display!");
|
|
|
|
|
tile_height = 16;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
MISSING_CASE(fb_format_modifier);
|
|
|
|
|
tile_height = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-02-10 17:16:10 +00:00
|
|
|
|
2015-03-23 11:10:32 +00:00
|
|
|
return tile_height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
intel_fb_align_height(struct drm_device *dev, unsigned int height,
|
|
|
|
|
uint32_t pixel_format, uint64_t fb_format_modifier)
|
|
|
|
|
{
|
|
|
|
|
return ALIGN(height, intel_tile_height(dev, pixel_format,
|
2015-09-21 10:45:32 +01:00
|
|
|
fb_format_modifier, 0));
|
2014-02-07 12:10:35 -08:00
|
|
|
}
|
|
|
|
|
|
2015-10-14 16:51:04 +02:00
|
|
|
static void
|
2015-03-23 11:10:35 +00:00
|
|
|
intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
|
|
|
|
|
const struct drm_plane_state *plane_state)
|
|
|
|
|
{
|
2015-10-14 16:51:05 +02:00
|
|
|
struct intel_rotation_info *info = &view->params.rotation_info;
|
2015-06-23 14:26:46 +01:00
|
|
|
unsigned int tile_height, tile_pitch;
|
2015-03-23 11:10:36 +00:00
|
|
|
|
2015-03-23 11:10:35 +00:00
|
|
|
*view = i915_ggtt_view_normal;
|
|
|
|
|
|
2015-03-23 11:10:36 +00:00
|
|
|
if (!plane_state)
|
2015-10-14 16:51:04 +02:00
|
|
|
return;
|
2015-03-23 11:10:36 +00:00
|
|
|
|
2015-03-23 11:10:37 +00:00
|
|
|
if (!intel_rotation_90_or_270(plane_state->rotation))
|
2015-10-14 16:51:04 +02:00
|
|
|
return;
|
2015-03-23 11:10:36 +00:00
|
|
|
|
2015-03-27 13:09:22 +02:00
|
|
|
*view = i915_ggtt_view_rotated;
|
2015-03-23 11:10:36 +00:00
|
|
|
|
|
|
|
|
info->height = fb->height;
|
|
|
|
|
info->pixel_format = fb->pixel_format;
|
|
|
|
|
info->pitch = fb->pitches[0];
|
2015-09-21 10:45:34 +01:00
|
|
|
info->uv_offset = fb->offsets[1];
|
2015-03-23 11:10:36 +00:00
|
|
|
info->fb_modifier = fb->modifier[0];
|
|
|
|
|
|
2015-06-23 14:26:46 +01:00
|
|
|
tile_height = intel_tile_height(fb->dev, fb->pixel_format,
|
2015-09-21 10:45:32 +01:00
|
|
|
fb->modifier[0], 0);
|
2015-06-23 14:26:46 +01:00
|
|
|
tile_pitch = PAGE_SIZE / tile_height;
|
|
|
|
|
info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
|
|
|
|
|
info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
|
|
|
|
|
info->size = info->width_pages * info->height_pages * PAGE_SIZE;
|
|
|
|
|
|
2015-09-21 10:45:34 +01:00
|
|
|
if (info->pixel_format == DRM_FORMAT_NV12) {
|
|
|
|
|
tile_height = intel_tile_height(fb->dev, fb->pixel_format,
|
|
|
|
|
fb->modifier[0], 1);
|
|
|
|
|
tile_pitch = PAGE_SIZE / tile_height;
|
|
|
|
|
info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
|
|
|
|
|
info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
|
|
|
|
|
tile_height);
|
|
|
|
|
info->size_uv = info->width_pages_uv * info->height_pages_uv *
|
|
|
|
|
PAGE_SIZE;
|
|
|
|
|
}
|
2015-03-23 11:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
2015-06-11 16:31:14 +03:00
|
|
|
static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
if (INTEL_INFO(dev_priv)->gen >= 9)
|
|
|
|
|
return 256 * 1024;
|
2015-06-11 16:31:15 +03:00
|
|
|
else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
|
2015-12-09 12:29:35 -08:00
|
|
|
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
2015-06-11 16:31:14 +03:00
|
|
|
return 128 * 1024;
|
|
|
|
|
else if (INTEL_INFO(dev_priv)->gen >= 4)
|
|
|
|
|
return 4 * 1024;
|
|
|
|
|
else
|
2015-06-11 16:31:16 +03:00
|
|
|
return 0;
|
2015-06-11 16:31:14 +03:00
|
|
|
}
|
|
|
|
|
|
2010-07-23 23:32:05 +01:00
|
|
|
int
|
2014-10-30 16:39:38 +00:00
|
|
|
intel_pin_and_fence_fb_obj(struct drm_plane *plane,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2015-08-18 13:40:06 +02:00
|
|
|
const struct drm_plane_state *plane_state)
|
2009-11-18 11:25:18 -05:00
|
|
|
{
|
2014-10-30 16:39:38 +00:00
|
|
|
struct drm_device *dev = fb->dev;
|
2011-02-21 14:43:56 +00:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-10-30 16:39:38 +00:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
2015-03-23 11:10:35 +00:00
|
|
|
struct i915_ggtt_view view;
|
2009-11-18 11:25:18 -05:00
|
|
|
u32 alignment;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2014-07-09 16:22:11 -07:00
|
|
|
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
|
|
|
|
2015-02-10 17:16:15 +00:00
|
|
|
switch (fb->modifier[0]) {
|
|
|
|
|
case DRM_FORMAT_MOD_NONE:
|
2015-06-11 16:31:14 +03:00
|
|
|
alignment = intel_linear_alignment(dev_priv);
|
2009-11-18 11:25:18 -05:00
|
|
|
break;
|
2015-02-10 17:16:15 +00:00
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
2013-07-03 21:06:02 +01:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
|
|
|
|
alignment = 256 * 1024;
|
|
|
|
|
else {
|
|
|
|
|
/* pin() will align the object as required by fence */
|
|
|
|
|
alignment = 0;
|
|
|
|
|
}
|
2009-11-18 11:25:18 -05:00
|
|
|
break;
|
2015-02-10 17:16:15 +00:00
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
2015-02-27 11:15:20 +00:00
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
|
|
|
if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
|
|
|
|
|
"Y tiling bo slipped through, driver bug!\n"))
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
alignment = 1 * 1024 * 1024;
|
|
|
|
|
break;
|
2009-11-18 11:25:18 -05:00
|
|
|
default:
|
2015-02-10 17:16:15 +00:00
|
|
|
MISSING_CASE(fb->modifier[0]);
|
|
|
|
|
return -EINVAL;
|
2009-11-18 11:25:18 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-14 16:51:04 +02:00
|
|
|
intel_fill_fb_ggtt_view(&view, fb, plane_state);
|
2015-03-23 11:10:35 +00:00
|
|
|
|
2013-03-05 14:52:39 +00: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;
|
|
|
|
|
|
2014-08-15 15:59:32 -03:00
|
|
|
/*
|
|
|
|
|
* Global gtt pte registers are special registers which actually forward
|
|
|
|
|
* writes to a chunk of system memory. Which means that there is no risk
|
|
|
|
|
* that the register values disappear as soon as we call
|
|
|
|
|
* intel_runtime_pm_put(), so it is correct to wrap only the
|
|
|
|
|
* pin/unpin/fence and not more.
|
|
|
|
|
*/
|
|
|
|
|
intel_runtime_pm_get(dev_priv);
|
|
|
|
|
|
2015-08-18 13:40:06 +02:00
|
|
|
ret = i915_gem_object_pin_to_display_plane(obj, alignment,
|
|
|
|
|
&view);
|
2010-09-14 12:50:34 +01:00
|
|
|
if (ret)
|
2015-09-23 13:27:09 +02:00
|
|
|
goto err_pm;
|
2009-11-18 11:25:18 -05: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.
|
|
|
|
|
*/
|
2015-10-29 18:54:38 -07:00
|
|
|
if (view.type == I915_GGTT_VIEW_NORMAL) {
|
|
|
|
|
ret = i915_gem_object_get_fence(obj);
|
|
|
|
|
if (ret == -EDEADLK) {
|
|
|
|
|
/*
|
|
|
|
|
* -EDEADLK means there are no free fences
|
|
|
|
|
* no pending flips.
|
|
|
|
|
*
|
|
|
|
|
* This is propagated to atomic, but it uses
|
|
|
|
|
* -EDEADLK to force a locking recovery, so
|
|
|
|
|
* change the returned error to -EBUSY.
|
|
|
|
|
*/
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
goto err_unpin;
|
|
|
|
|
} else if (ret)
|
|
|
|
|
goto err_unpin;
|
2011-12-14 13:57:08 +01:00
|
|
|
|
2015-10-29 18:54:38 -07:00
|
|
|
i915_gem_object_pin_fence(obj);
|
|
|
|
|
}
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2014-08-15 15:59:32 -03:00
|
|
|
intel_runtime_pm_put(dev_priv);
|
2009-11-18 11:25:18 -05:00
|
|
|
return 0;
|
2010-09-14 12:50:34 +01:00
|
|
|
|
|
|
|
|
err_unpin:
|
2015-03-23 11:10:35 +00:00
|
|
|
i915_gem_object_unpin_from_display_plane(obj, &view);
|
2015-09-23 13:27:09 +02:00
|
|
|
err_pm:
|
2014-08-15 15:59:32 -03:00
|
|
|
intel_runtime_pm_put(dev_priv);
|
2010-09-14 12:50:34 +01:00
|
|
|
return ret;
|
2009-11-18 11:25:18 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-23 11:10:34 +00:00
|
|
|
static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
|
|
|
|
|
const struct drm_plane_state *plane_state)
|
2011-12-14 13:57:08 +01:00
|
|
|
{
|
2015-03-23 11:10:34 +00:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
2015-03-23 11:10:35 +00:00
|
|
|
struct i915_ggtt_view view;
|
2015-03-23 11:10:34 +00:00
|
|
|
|
2014-07-09 16:22:11 -07:00
|
|
|
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
|
|
|
|
|
|
2015-10-14 16:51:04 +02:00
|
|
|
intel_fill_fb_ggtt_view(&view, fb, plane_state);
|
2015-03-23 11:10:35 +00:00
|
|
|
|
2015-10-29 18:54:38 -07:00
|
|
|
if (view.type == I915_GGTT_VIEW_NORMAL)
|
|
|
|
|
i915_gem_object_unpin_fence(obj);
|
|
|
|
|
|
2015-03-23 11:10:35 +00:00
|
|
|
i915_gem_object_unpin_from_display_plane(obj, &view);
|
2011-12-14 13:57:08 +01:00
|
|
|
}
|
|
|
|
|
|
2012-07-05 12:17:30 +02:00
|
|
|
/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
|
|
|
|
|
* is assumed to be a power-of-two. */
|
2015-06-11 16:31:14 +03:00
|
|
|
unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
|
|
|
|
|
int *x, int *y,
|
2013-02-21 20:04:31 +00:00
|
|
|
unsigned int tiling_mode,
|
|
|
|
|
unsigned int cpp,
|
|
|
|
|
unsigned int pitch)
|
2012-07-05 12:17:30 +02:00
|
|
|
{
|
2013-02-21 20:04:31 +00:00
|
|
|
if (tiling_mode != I915_TILING_NONE) {
|
|
|
|
|
unsigned int tile_rows, tiles;
|
2012-07-05 12:17:30 +02:00
|
|
|
|
2013-02-21 20:04:31 +00:00
|
|
|
tile_rows = *y / 8;
|
|
|
|
|
*y %= 8;
|
2012-07-05 12:17:30 +02:00
|
|
|
|
2013-02-21 20:04:31 +00:00
|
|
|
tiles = *x / (512/cpp);
|
|
|
|
|
*x %= 512/cpp;
|
|
|
|
|
|
|
|
|
|
return tile_rows * pitch * 8 + tiles * 4096;
|
|
|
|
|
} else {
|
2015-06-11 16:31:14 +03:00
|
|
|
unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
|
2013-02-21 20:04:31 +00:00
|
|
|
unsigned int offset;
|
|
|
|
|
|
|
|
|
|
offset = *y * pitch + *x * cpp;
|
2015-06-11 16:31:14 +03:00
|
|
|
*y = (offset & alignment) / pitch;
|
|
|
|
|
*x = ((offset & alignment) - *y * pitch) / cpp;
|
|
|
|
|
return offset & ~alignment;
|
2013-02-21 20:04:31 +00:00
|
|
|
}
|
2012-07-05 12:17:30 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:50 +00:00
|
|
|
static int i9xx_format_to_fourcc(int format)
|
2014-03-07 08:57:48 -08:00
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case DISPPLANE_8BPP:
|
|
|
|
|
return DRM_FORMAT_C8;
|
|
|
|
|
case DISPPLANE_BGRX555:
|
|
|
|
|
return DRM_FORMAT_XRGB1555;
|
|
|
|
|
case DISPPLANE_BGRX565:
|
|
|
|
|
return DRM_FORMAT_RGB565;
|
|
|
|
|
default:
|
|
|
|
|
case DISPPLANE_BGRX888:
|
|
|
|
|
return DRM_FORMAT_XRGB8888;
|
|
|
|
|
case DISPPLANE_RGBX888:
|
|
|
|
|
return DRM_FORMAT_XBGR8888;
|
|
|
|
|
case DISPPLANE_BGRX101010:
|
|
|
|
|
return DRM_FORMAT_XRGB2101010;
|
|
|
|
|
case DISPPLANE_RGBX101010:
|
|
|
|
|
return DRM_FORMAT_XBGR2101010;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:51 +00:00
|
|
|
static int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
|
|
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case PLANE_CTL_FORMAT_RGB_565:
|
|
|
|
|
return DRM_FORMAT_RGB565;
|
|
|
|
|
default:
|
|
|
|
|
case PLANE_CTL_FORMAT_XRGB_8888:
|
|
|
|
|
if (rgb_order) {
|
|
|
|
|
if (alpha)
|
|
|
|
|
return DRM_FORMAT_ABGR8888;
|
|
|
|
|
else
|
|
|
|
|
return DRM_FORMAT_XBGR8888;
|
|
|
|
|
} else {
|
|
|
|
|
if (alpha)
|
|
|
|
|
return DRM_FORMAT_ARGB8888;
|
|
|
|
|
else
|
|
|
|
|
return DRM_FORMAT_XRGB8888;
|
|
|
|
|
}
|
|
|
|
|
case PLANE_CTL_FORMAT_XRGB_2101010:
|
|
|
|
|
if (rgb_order)
|
|
|
|
|
return DRM_FORMAT_XBGR2101010;
|
|
|
|
|
else
|
|
|
|
|
return DRM_FORMAT_XRGB2101010;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:52 +00:00
|
|
|
static bool
|
2015-03-26 12:17:05 +01:00
|
|
|
intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_initial_plane_config *plane_config)
|
2014-03-07 08:57:48 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2015-09-23 12:52:23 -03:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2014-03-07 08:57:48 -08:00
|
|
|
struct drm_i915_gem_object *obj = NULL;
|
|
|
|
|
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
2015-02-05 17:22:18 +00:00
|
|
|
struct drm_framebuffer *fb = &plane_config->fb->base;
|
2015-02-10 23:12:27 +01:00
|
|
|
u32 base_aligned = round_down(plane_config->base, PAGE_SIZE);
|
|
|
|
|
u32 size_aligned = round_up(plane_config->base + plane_config->size,
|
|
|
|
|
PAGE_SIZE);
|
|
|
|
|
|
|
|
|
|
size_aligned -= base_aligned;
|
2014-03-07 08:57:48 -08:00
|
|
|
|
2014-03-10 08:07:02 +00:00
|
|
|
if (plane_config->size == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-09-23 12:52:23 -03:00
|
|
|
/* If the FB is too big, just don't use it since fbdev is not very
|
|
|
|
|
* important and we should probably use that space with FBC or other
|
|
|
|
|
* features. */
|
|
|
|
|
if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size)
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-02-10 23:12:27 +01:00
|
|
|
obj = i915_gem_object_create_stolen_for_preallocated(dev,
|
|
|
|
|
base_aligned,
|
|
|
|
|
base_aligned,
|
|
|
|
|
size_aligned);
|
2014-03-07 08:57:48 -08:00
|
|
|
if (!obj)
|
2014-03-07 08:57:55 -08:00
|
|
|
return false;
|
2014-03-07 08:57:48 -08:00
|
|
|
|
2015-01-20 12:51:44 +00:00
|
|
|
obj->tiling_mode = plane_config->tiling;
|
|
|
|
|
if (obj->tiling_mode == I915_TILING_X)
|
2015-02-05 17:22:16 +00:00
|
|
|
obj->stride = fb->pitches[0];
|
2014-03-07 08:57:48 -08:00
|
|
|
|
2015-02-05 17:22:16 +00:00
|
|
|
mode_cmd.pixel_format = fb->pixel_format;
|
|
|
|
|
mode_cmd.width = fb->width;
|
|
|
|
|
mode_cmd.height = fb->height;
|
|
|
|
|
mode_cmd.pitches[0] = fb->pitches[0];
|
2015-02-10 17:16:09 +00:00
|
|
|
mode_cmd.modifier[0] = fb->modifier[0];
|
|
|
|
|
mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
|
2014-03-07 08:57:48 -08:00
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
2015-02-05 17:22:16 +00:00
|
|
|
if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
|
2014-03-07 08:57:55 -08:00
|
|
|
&mode_cmd, obj)) {
|
2014-03-07 08:57:48 -08:00
|
|
|
DRM_DEBUG_KMS("intel fb init failed\n");
|
|
|
|
|
goto out_unref_obj;
|
|
|
|
|
}
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2014-03-07 08:57:55 -08:00
|
|
|
|
2015-03-26 12:17:05 +01:00
|
|
|
DRM_DEBUG_KMS("initial plane fb obj %p\n", obj);
|
2014-03-07 08:57:55 -08:00
|
|
|
return true;
|
2014-03-07 08:57:48 -08:00
|
|
|
|
|
|
|
|
out_unref_obj:
|
|
|
|
|
drm_gem_object_unreference(&obj->base);
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2014-03-07 08:57:55 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 13:10:04 -08:00
|
|
|
/* Update plane->state->fb to match plane->fb after driver-internal updates */
|
|
|
|
|
static void
|
|
|
|
|
update_state_fb(struct drm_plane *plane)
|
|
|
|
|
{
|
|
|
|
|
if (plane->fb == plane->state->fb)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (plane->state->fb)
|
|
|
|
|
drm_framebuffer_unreference(plane->state->fb);
|
|
|
|
|
plane->state->fb = plane->fb;
|
|
|
|
|
if (plane->state->fb)
|
|
|
|
|
drm_framebuffer_reference(plane->state->fb);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:52 +00:00
|
|
|
static void
|
2015-03-26 12:17:05 +01:00
|
|
|
intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|
|
|
|
struct intel_initial_plane_config *plane_config)
|
2014-03-07 08:57:55 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
2014-10-09 12:57:43 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-03-07 08:57:55 -08:00
|
|
|
struct drm_crtc *c;
|
|
|
|
|
struct intel_crtc *i;
|
2014-07-08 07:50:07 -07:00
|
|
|
struct drm_i915_gem_object *obj;
|
2015-03-26 12:42:24 +01:00
|
|
|
struct drm_plane *primary = intel_crtc->base.primary;
|
2015-07-13 16:30:18 +02:00
|
|
|
struct drm_plane_state *plane_state = primary->state;
|
2015-12-03 11:37:36 -08:00
|
|
|
struct drm_crtc_state *crtc_state = intel_crtc->base.state;
|
|
|
|
|
struct intel_plane *intel_plane = to_intel_plane(primary);
|
2015-12-03 11:37:38 -08:00
|
|
|
struct intel_plane_state *intel_state =
|
|
|
|
|
to_intel_plane_state(plane_state);
|
2015-03-26 12:42:24 +01:00
|
|
|
struct drm_framebuffer *fb;
|
2014-03-07 08:57:55 -08:00
|
|
|
|
2015-02-05 17:22:18 +00:00
|
|
|
if (!plane_config->fb)
|
2014-03-07 08:57:55 -08:00
|
|
|
return;
|
|
|
|
|
|
2015-03-26 12:17:05 +01:00
|
|
|
if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) {
|
2015-03-26 12:42:24 +01:00
|
|
|
fb = &plane_config->fb->base;
|
|
|
|
|
goto valid_fb;
|
2015-02-05 18:30:20 +00:00
|
|
|
}
|
2014-03-07 08:57:55 -08:00
|
|
|
|
2015-02-05 17:22:18 +00:00
|
|
|
kfree(plane_config->fb);
|
2014-03-07 08:57:55 -08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Failed to alloc the obj, check to see if we should share
|
|
|
|
|
* an fb with another CRTC instead
|
|
|
|
|
*/
|
2014-05-13 23:32:24 +01:00
|
|
|
for_each_crtc(dev, c) {
|
2014-03-07 08:57:55 -08:00
|
|
|
i = to_intel_crtc(c);
|
|
|
|
|
|
|
|
|
|
if (c == &intel_crtc->base)
|
|
|
|
|
continue;
|
|
|
|
|
|
2014-07-08 07:50:07 -07:00
|
|
|
if (!i->active)
|
|
|
|
|
continue;
|
|
|
|
|
|
2015-03-26 12:42:24 +01:00
|
|
|
fb = c->primary->fb;
|
|
|
|
|
if (!fb)
|
2014-03-07 08:57:55 -08:00
|
|
|
continue;
|
|
|
|
|
|
2015-03-26 12:42:24 +01:00
|
|
|
obj = intel_fb_obj(fb);
|
2014-07-08 07:50:07 -07:00
|
|
|
if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
|
2015-03-26 12:42:24 +01:00
|
|
|
drm_framebuffer_reference(fb);
|
|
|
|
|
goto valid_fb;
|
2014-03-07 08:57:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-26 12:42:24 +01:00
|
|
|
|
2015-12-03 11:37:36 -08:00
|
|
|
/*
|
|
|
|
|
* We've failed to reconstruct the BIOS FB. Current display state
|
|
|
|
|
* indicates that the primary plane is visible, but has a NULL FB,
|
|
|
|
|
* which will lead to problems later if we don't fix it up. The
|
|
|
|
|
* simplest solution is to just disable the primary plane now and
|
|
|
|
|
* pretend the BIOS never had it enabled.
|
|
|
|
|
*/
|
|
|
|
|
to_intel_plane_state(plane_state)->visible = false;
|
|
|
|
|
crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
|
|
|
|
|
intel_pre_disable_primary(&intel_crtc->base);
|
|
|
|
|
intel_plane->disable_plane(primary, &intel_crtc->base);
|
|
|
|
|
|
2015-03-26 12:42:24 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
valid_fb:
|
2015-11-13 19:16:13 +02:00
|
|
|
plane_state->src_x = 0;
|
|
|
|
|
plane_state->src_y = 0;
|
2015-07-13 16:30:18 +02:00
|
|
|
plane_state->src_w = fb->width << 16;
|
|
|
|
|
plane_state->src_h = fb->height << 16;
|
|
|
|
|
|
2015-11-13 19:16:13 +02:00
|
|
|
plane_state->crtc_x = 0;
|
|
|
|
|
plane_state->crtc_y = 0;
|
2015-07-13 16:30:18 +02:00
|
|
|
plane_state->crtc_w = fb->width;
|
|
|
|
|
plane_state->crtc_h = fb->height;
|
|
|
|
|
|
2015-12-03 11:37:38 -08:00
|
|
|
intel_state->src.x1 = plane_state->src_x;
|
|
|
|
|
intel_state->src.y1 = plane_state->src_y;
|
|
|
|
|
intel_state->src.x2 = plane_state->src_x + plane_state->src_w;
|
|
|
|
|
intel_state->src.y2 = plane_state->src_y + plane_state->src_h;
|
|
|
|
|
intel_state->dst.x1 = plane_state->crtc_x;
|
|
|
|
|
intel_state->dst.y1 = plane_state->crtc_y;
|
|
|
|
|
intel_state->dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
|
|
|
|
|
intel_state->dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
|
|
|
|
|
|
2015-03-26 12:42:24 +01:00
|
|
|
obj = intel_fb_obj(fb);
|
|
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
|
|
|
|
dev_priv->preserve_bios_swizzle = true;
|
|
|
|
|
|
2015-07-13 16:30:18 +02:00
|
|
|
drm_framebuffer_reference(fb);
|
|
|
|
|
primary->fb = primary->state->fb = fb;
|
2015-06-01 12:49:54 +02:00
|
|
|
primary->crtc = primary->state->crtc = &intel_crtc->base;
|
|
|
|
|
intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
|
2015-06-24 21:59:34 +03:00
|
|
|
obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
|
2014-03-07 08:57:48 -08:00
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:55:01 +02:00
|
|
|
static void i9xx_update_primary_plane(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
|
int x, int y)
|
2010-08-02 12:07:50 -07: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);
|
2015-04-21 17:12:53 +03:00
|
|
|
struct drm_plane *primary = crtc->primary;
|
|
|
|
|
bool visible = to_intel_plane_state(primary->state)->visible;
|
2014-08-27 17:48:41 +03:00
|
|
|
struct drm_i915_gem_object *obj;
|
2010-08-02 12:07:50 -07:00
|
|
|
int plane = intel_crtc->plane;
|
2012-07-05 12:17:29 +02:00
|
|
|
unsigned long linear_offset;
|
2010-08-02 12:07:50 -07:00
|
|
|
u32 dspcntr;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = DSPCNTR(plane);
|
2014-08-22 14:06:04 +05:30
|
|
|
int pixel_size;
|
2014-08-08 21:51:10 +03:00
|
|
|
|
2015-04-21 17:12:53 +03:00
|
|
|
if (!visible || !fb) {
|
2014-08-08 21:51:11 +03:00
|
|
|
I915_WRITE(reg, 0);
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4)
|
|
|
|
|
I915_WRITE(DSPSURF(plane), 0);
|
|
|
|
|
else
|
|
|
|
|
I915_WRITE(DSPADDR(plane), 0);
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-27 17:48:41 +03:00
|
|
|
obj = intel_fb_obj(fb);
|
|
|
|
|
if (WARN_ON(obj == NULL))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
|
|
|
2014-08-08 21:51:10 +03:00
|
|
|
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
|
|
|
|
|
2014-08-08 21:51:11 +03:00
|
|
|
dspcntr |= DISPLAY_PLANE_ENABLE;
|
2014-08-08 21:51:10 +03:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
|
|
|
|
if (intel_crtc->pipe == PIPE_B)
|
|
|
|
|
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
|
|
|
|
|
|
|
|
|
/* pipesrc and dspsize control the size that is scaled from,
|
|
|
|
|
* which should always be the user's requested size.
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(DSPSIZE(plane),
|
2015-01-15 14:55:25 +02:00
|
|
|
((intel_crtc->config->pipe_src_h - 1) << 16) |
|
|
|
|
|
(intel_crtc->config->pipe_src_w - 1));
|
2014-08-08 21:51:10 +03:00
|
|
|
I915_WRITE(DSPPOS(plane), 0);
|
2014-10-16 20:52:34 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
|
|
|
|
|
I915_WRITE(PRIMSIZE(plane),
|
2015-01-15 14:55:25 +02:00
|
|
|
((intel_crtc->config->pipe_src_h - 1) << 16) |
|
|
|
|
|
(intel_crtc->config->pipe_src_w - 1));
|
2014-10-16 20:52:34 +03:00
|
|
|
I915_WRITE(PRIMPOS(plane), 0);
|
|
|
|
|
I915_WRITE(PRIMCNSTALPHA(plane), 0);
|
2014-08-08 21:51:10 +03:00
|
|
|
}
|
2010-08-02 12:07:50 -07:00
|
|
|
|
2012-10-31 17:50:14 +02:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
|
case DRM_FORMAT_C8:
|
2010-08-02 12:07:50 -07:00
|
|
|
dspcntr |= DISPPLANE_8BPP;
|
|
|
|
|
break;
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_XRGB1555:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX555;
|
2010-08-02 12:07:50 -07:00
|
|
|
break;
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX565;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX888;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
|
dspcntr |= DISPPLANE_RGBX888;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX101010;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
|
dspcntr |= DISPPLANE_RGBX101010;
|
2010-08-02 12:07:50 -07:00
|
|
|
break;
|
|
|
|
|
default:
|
2013-03-27 00:45:00 +01:00
|
|
|
BUG();
|
2010-08-02 12:07:50 -07:00
|
|
|
}
|
2012-10-31 17:50:14 +02:00
|
|
|
|
2014-08-08 21:51:10 +03:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4 &&
|
|
|
|
|
obj->tiling_mode != I915_TILING_NONE)
|
|
|
|
|
dspcntr |= DISPPLANE_TILED;
|
2010-08-02 12:07:50 -07:00
|
|
|
|
2013-06-07 10:47:01 +03:00
|
|
|
if (IS_G4X(dev))
|
|
|
|
|
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
|
|
|
2014-08-27 16:51:22 +03:00
|
|
|
linear_offset = y * fb->pitches[0] + x * pixel_size;
|
2010-08-02 12:07:50 -07:00
|
|
|
|
2012-07-05 12:17:30 +02:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
intel_crtc->dspaddr_offset =
|
2015-06-11 16:31:14 +03:00
|
|
|
intel_gen4_compute_page_offset(dev_priv,
|
|
|
|
|
&x, &y, obj->tiling_mode,
|
2014-08-27 16:51:22 +03:00
|
|
|
pixel_size,
|
2013-02-21 20:04:31 +00:00
|
|
|
fb->pitches[0]);
|
2012-07-05 12:17:30 +02:00
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
|
|
|
|
} else {
|
2012-07-05 12:17:29 +02:00
|
|
|
intel_crtc->dspaddr_offset = linear_offset;
|
2012-07-05 12:17:30 +02:00
|
|
|
}
|
2012-07-05 12:17:29 +02:00
|
|
|
|
2015-01-21 16:35:41 -08:00
|
|
|
if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
|
2014-08-22 14:06:04 +05:30
|
|
|
dspcntr |= DISPPLANE_ROTATE_180;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
x += (intel_crtc->config->pipe_src_w - 1);
|
|
|
|
|
y += (intel_crtc->config->pipe_src_h - 1);
|
2014-08-22 14:06:04 +05:30
|
|
|
|
|
|
|
|
/* Finding the last pixel of the last line of the display
|
|
|
|
|
data and adding to linear_offset*/
|
|
|
|
|
linear_offset +=
|
2015-01-15 14:55:25 +02:00
|
|
|
(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
|
|
(intel_crtc->config->pipe_src_w - 1) * pixel_size;
|
2014-08-22 14:06:04 +05:30
|
|
|
}
|
|
|
|
|
|
2015-09-14 15:20:03 -03:00
|
|
|
intel_crtc->adjusted_x = x;
|
|
|
|
|
intel_crtc->adjusted_y = y;
|
|
|
|
|
|
2014-08-22 14:06:04 +05:30
|
|
|
I915_WRITE(reg, dspcntr);
|
|
|
|
|
|
2011-12-20 00:06:49 +02:00
|
|
|
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
2010-09-17 00:32:17 +01:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2014-01-24 10:31:44 +01:00
|
|
|
I915_WRITE(DSPSURF(plane),
|
|
|
|
|
i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
|
2010-09-11 13:48:45 +01:00
|
|
|
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
|
2012-07-05 12:17:29 +02:00
|
|
|
I915_WRITE(DSPLINOFF(plane), linear_offset);
|
2010-09-11 13:48:45 +01:00
|
|
|
} else
|
2013-07-05 14:41:04 -07:00
|
|
|
I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset);
|
2010-09-11 13:48:45 +01:00
|
|
|
POSTING_READ(reg);
|
2011-06-24 12:19:23 -07:00
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:55:01 +02:00
|
|
|
static void ironlake_update_primary_plane(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
|
int x, int y)
|
2011-06-24 12:19:23 -07: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);
|
2015-04-21 17:12:53 +03:00
|
|
|
struct drm_plane *primary = crtc->primary;
|
|
|
|
|
bool visible = to_intel_plane_state(primary->state)->visible;
|
2014-08-27 17:48:41 +03:00
|
|
|
struct drm_i915_gem_object *obj;
|
2011-06-24 12:19:23 -07:00
|
|
|
int plane = intel_crtc->plane;
|
2012-07-05 12:17:29 +02:00
|
|
|
unsigned long linear_offset;
|
2011-06-24 12:19:23 -07:00
|
|
|
u32 dspcntr;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = DSPCNTR(plane);
|
2014-08-22 14:06:04 +05:30
|
|
|
int pixel_size;
|
2014-08-08 21:51:10 +03:00
|
|
|
|
2015-04-21 17:12:53 +03:00
|
|
|
if (!visible || !fb) {
|
2014-08-08 21:51:11 +03:00
|
|
|
I915_WRITE(reg, 0);
|
|
|
|
|
I915_WRITE(DSPSURF(plane), 0);
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-27 17:48:41 +03:00
|
|
|
obj = intel_fb_obj(fb);
|
|
|
|
|
if (WARN_ON(obj == NULL))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
|
|
|
|
|
|
2014-08-08 21:51:10 +03:00
|
|
|
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
|
|
|
|
|
2014-08-08 21:51:11 +03:00
|
|
|
dspcntr |= DISPLAY_PLANE_ENABLE;
|
2014-08-08 21:51:10 +03:00
|
|
|
|
|
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
|
|
|
|
dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
|
2011-06-24 12:19:23 -07:00
|
|
|
|
2012-10-31 17:50:14 +02:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
|
case DRM_FORMAT_C8:
|
2011-06-24 12:19:23 -07:00
|
|
|
dspcntr |= DISPPLANE_8BPP;
|
|
|
|
|
break;
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX565;
|
2011-06-24 12:19:23 -07:00
|
|
|
break;
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX888;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
|
dspcntr |= DISPPLANE_RGBX888;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
|
dspcntr |= DISPPLANE_BGRX101010;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
|
dspcntr |= DISPPLANE_RGBX101010;
|
2011-06-24 12:19:23 -07:00
|
|
|
break;
|
|
|
|
|
default:
|
2013-03-27 00:45:00 +01:00
|
|
|
BUG();
|
2011-06-24 12:19:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
|
|
|
|
dspcntr |= DISPPLANE_TILED;
|
|
|
|
|
|
2014-08-08 21:51:10 +03:00
|
|
|
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
|
2013-08-23 19:51:28 -03:00
|
|
|
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
2011-06-24 12:19:23 -07:00
|
|
|
|
2014-08-27 16:51:22 +03:00
|
|
|
linear_offset = y * fb->pitches[0] + x * pixel_size;
|
2012-07-05 12:17:30 +02:00
|
|
|
intel_crtc->dspaddr_offset =
|
2015-06-11 16:31:14 +03:00
|
|
|
intel_gen4_compute_page_offset(dev_priv,
|
|
|
|
|
&x, &y, obj->tiling_mode,
|
2014-08-27 16:51:22 +03:00
|
|
|
pixel_size,
|
2013-02-21 20:04:31 +00:00
|
|
|
fb->pitches[0]);
|
2012-07-05 12:17:30 +02:00
|
|
|
linear_offset -= intel_crtc->dspaddr_offset;
|
2015-01-21 16:35:41 -08:00
|
|
|
if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
|
2014-08-22 14:06:04 +05:30
|
|
|
dspcntr |= DISPPLANE_ROTATE_180;
|
|
|
|
|
|
|
|
|
|
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
|
2015-01-15 14:55:25 +02:00
|
|
|
x += (intel_crtc->config->pipe_src_w - 1);
|
|
|
|
|
y += (intel_crtc->config->pipe_src_h - 1);
|
2014-08-22 14:06:04 +05:30
|
|
|
|
|
|
|
|
/* Finding the last pixel of the last line of the display
|
|
|
|
|
data and adding to linear_offset*/
|
|
|
|
|
linear_offset +=
|
2015-01-15 14:55:25 +02:00
|
|
|
(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
|
|
|
|
|
(intel_crtc->config->pipe_src_w - 1) * pixel_size;
|
2014-08-22 14:06:04 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-14 15:20:03 -03:00
|
|
|
intel_crtc->adjusted_x = x;
|
|
|
|
|
intel_crtc->adjusted_y = y;
|
|
|
|
|
|
2014-08-22 14:06:04 +05:30
|
|
|
I915_WRITE(reg, dspcntr);
|
2011-06-24 12:19:23 -07:00
|
|
|
|
2011-12-20 00:06:49 +02:00
|
|
|
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
2014-01-24 10:31:44 +01:00
|
|
|
I915_WRITE(DSPSURF(plane),
|
|
|
|
|
i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
|
2013-11-02 21:07:33 -07:00
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
2012-10-29 12:14:21 +00:00
|
|
|
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
|
|
|
|
|
} else {
|
|
|
|
|
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
|
|
|
|
|
I915_WRITE(DSPLINOFF(plane), linear_offset);
|
|
|
|
|
}
|
2011-06-24 12:19:23 -07:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 11:15:18 +00:00
|
|
|
u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
|
|
|
|
|
uint32_t pixel_format)
|
|
|
|
|
{
|
|
|
|
|
u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The stride is either expressed as a multiple of 64 bytes
|
|
|
|
|
* chunks for linear buffers or in number of tiles for tiled
|
|
|
|
|
* buffers.
|
|
|
|
|
*/
|
|
|
|
|
switch (fb_modifier) {
|
|
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
|
|
return 64;
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
|
|
if (INTEL_INFO(dev)->gen == 2)
|
|
|
|
|
return 128;
|
|
|
|
|
return 512;
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
/* No need to check for old gens and Y tiling since this is
|
|
|
|
|
* about the display engine and those will be blocked before
|
|
|
|
|
* we get here.
|
|
|
|
|
*/
|
|
|
|
|
return 128;
|
|
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
|
|
|
if (bits_per_pixel == 8)
|
|
|
|
|
return 64;
|
|
|
|
|
else
|
|
|
|
|
return 128;
|
|
|
|
|
default:
|
|
|
|
|
MISSING_CASE(fb_modifier);
|
|
|
|
|
return 64;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-30 13:26:15 +02:00
|
|
|
u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
|
|
|
|
|
struct drm_i915_gem_object *obj,
|
|
|
|
|
unsigned int plane)
|
2015-03-23 11:10:37 +00:00
|
|
|
{
|
2015-10-14 16:51:06 +02:00
|
|
|
struct i915_ggtt_view view;
|
2015-09-21 10:45:35 +01:00
|
|
|
struct i915_vma *vma;
|
2015-10-30 13:26:15 +02:00
|
|
|
u64 offset;
|
2015-03-23 11:10:37 +00:00
|
|
|
|
2015-10-14 16:51:06 +02:00
|
|
|
intel_fill_fb_ggtt_view(&view, intel_plane->base.fb,
|
|
|
|
|
intel_plane->base.state);
|
2015-03-23 11:10:37 +00:00
|
|
|
|
2015-10-14 16:51:06 +02:00
|
|
|
vma = i915_gem_obj_to_ggtt_view(obj, &view);
|
2015-09-21 10:45:35 +01:00
|
|
|
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
|
2015-10-14 16:51:06 +02:00
|
|
|
view.type))
|
2015-09-21 10:45:35 +01:00
|
|
|
return -1;
|
|
|
|
|
|
2015-10-30 13:26:15 +02:00
|
|
|
offset = vma->node.start;
|
2015-09-21 10:45:35 +01:00
|
|
|
|
|
|
|
|
if (plane == 1) {
|
2015-10-14 16:51:05 +02:00
|
|
|
offset += vma->ggtt_view.params.rotation_info.uv_start_page *
|
2015-09-21 10:45:35 +01:00
|
|
|
PAGE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-30 13:26:15 +02:00
|
|
|
WARN_ON(upper_32_bits(offset));
|
|
|
|
|
|
|
|
|
|
return lower_32_bits(offset);
|
2015-03-23 11:10:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:15 +02:00
|
|
|
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, id), 0);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, id), 0);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, id), 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-07 15:28:45 -07:00
|
|
|
/*
|
|
|
|
|
* This function detaches (aka. unbinds) unused scalers in hardware
|
|
|
|
|
*/
|
2015-06-15 12:33:48 +02:00
|
|
|
static void skl_detach_scalers(struct intel_crtc *intel_crtc)
|
2015-04-07 15:28:45 -07:00
|
|
|
{
|
|
|
|
|
struct intel_crtc_scaler_state *scaler_state;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
scaler_state = &intel_crtc->config->scaler_state;
|
|
|
|
|
|
|
|
|
|
/* loop through and disable scalers that aren't in use */
|
|
|
|
|
for (i = 0; i < intel_crtc->num_scalers; i++) {
|
2015-07-13 16:30:15 +02:00
|
|
|
if (!scaler_state->scalers[i].in_use)
|
|
|
|
|
skl_detach_scaler(intel_crtc, i);
|
2015-04-07 15:28:45 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-27 13:48:39 -07:00
|
|
|
u32 skl_plane_ctl_format(uint32_t pixel_format)
|
2013-07-03 21:06:04 +01:00
|
|
|
{
|
2015-04-27 13:48:39 -07:00
|
|
|
switch (pixel_format) {
|
2015-05-12 16:13:17 +01:00
|
|
|
case DRM_FORMAT_C8:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_INDEXED;
|
2013-07-03 21:06:04 +01:00
|
|
|
case DRM_FORMAT_RGB565:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_RGB_565;
|
2013-07-03 21:06:04 +01:00
|
|
|
case DRM_FORMAT_XBGR8888:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
|
2015-04-27 13:48:39 -07:00
|
|
|
case DRM_FORMAT_XRGB8888:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_XRGB_8888;
|
2015-04-27 13:48:39 -07:00
|
|
|
/*
|
|
|
|
|
* XXX: For ARBG/ABGR formats we default to expecting scanout buffers
|
|
|
|
|
* to be already pre-multiplied. We need to add a knob (or a different
|
|
|
|
|
* DRM_FORMAT) for user-space to configure that.
|
|
|
|
|
*/
|
2015-02-10 13:15:49 +02:00
|
|
|
case DRM_FORMAT_ABGR8888:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX |
|
2015-04-27 13:48:39 -07:00
|
|
|
PLANE_CTL_ALPHA_SW_PREMULTIPLY;
|
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_XRGB_8888 |
|
2015-04-27 13:48:39 -07:00
|
|
|
PLANE_CTL_ALPHA_SW_PREMULTIPLY;
|
2013-07-03 21:06:04 +01:00
|
|
|
case DRM_FORMAT_XRGB2101010:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_XRGB_2101010;
|
2013-07-03 21:06:04 +01:00
|
|
|
case DRM_FORMAT_XBGR2101010:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_ORDER_RGBX | PLANE_CTL_FORMAT_XRGB_2101010;
|
2015-04-27 13:48:39 -07:00
|
|
|
case DRM_FORMAT_YUYV:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
|
2015-04-27 13:48:39 -07:00
|
|
|
case DRM_FORMAT_YVYU:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
|
2015-04-27 13:48:39 -07:00
|
|
|
case DRM_FORMAT_UYVY:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
|
2015-04-27 13:48:39 -07:00
|
|
|
case DRM_FORMAT_VYUY:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
|
2013-07-03 21:06:04 +01:00
|
|
|
default:
|
2015-05-12 16:13:16 +01:00
|
|
|
MISSING_CASE(pixel_format);
|
2013-07-03 21:06:04 +01:00
|
|
|
}
|
2015-05-12 16:13:14 +01:00
|
|
|
|
2015-05-15 15:07:02 +01:00
|
|
|
return 0;
|
2015-04-27 13:48:39 -07:00
|
|
|
}
|
2013-07-03 21:06:04 +01:00
|
|
|
|
2015-04-27 13:48:39 -07:00
|
|
|
u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
|
|
|
|
|
{
|
|
|
|
|
switch (fb_modifier) {
|
2015-02-10 17:16:11 +00:00
|
|
|
case DRM_FORMAT_MOD_NONE:
|
2013-07-03 21:06:04 +01:00
|
|
|
break;
|
2015-02-10 17:16:11 +00:00
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_TILED_X;
|
2015-02-27 11:15:18 +00:00
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_TILED_Y;
|
2015-02-27 11:15:18 +00:00
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_TILED_YF;
|
2013-07-03 21:06:04 +01:00
|
|
|
default:
|
2015-04-27 13:48:39 -07:00
|
|
|
MISSING_CASE(fb_modifier);
|
2013-07-03 21:06:04 +01:00
|
|
|
}
|
2015-05-12 16:13:14 +01:00
|
|
|
|
2015-05-15 15:07:02 +01:00
|
|
|
return 0;
|
2015-04-27 13:48:39 -07:00
|
|
|
}
|
2013-07-03 21:06:04 +01:00
|
|
|
|
2015-04-27 13:48:39 -07:00
|
|
|
u32 skl_plane_ctl_rotation(unsigned int rotation)
|
|
|
|
|
{
|
2015-04-10 14:37:29 +05:30
|
|
|
switch (rotation) {
|
2015-04-27 13:48:39 -07:00
|
|
|
case BIT(DRM_ROTATE_0):
|
|
|
|
|
break;
|
2015-05-20 13:40:48 +05:30
|
|
|
/*
|
|
|
|
|
* DRM_ROTATE_ is counter clockwise to stay compatible with Xrandr
|
|
|
|
|
* while i915 HW rotation is clockwise, thats why this swapping.
|
|
|
|
|
*/
|
2015-04-10 14:37:29 +05:30
|
|
|
case BIT(DRM_ROTATE_90):
|
2015-05-20 13:40:48 +05:30
|
|
|
return PLANE_CTL_ROTATE_270;
|
2015-04-10 14:37:29 +05:30
|
|
|
case BIT(DRM_ROTATE_180):
|
2015-05-15 15:07:02 +01:00
|
|
|
return PLANE_CTL_ROTATE_180;
|
2015-04-10 14:37:29 +05:30
|
|
|
case BIT(DRM_ROTATE_270):
|
2015-05-20 13:40:48 +05:30
|
|
|
return PLANE_CTL_ROTATE_90;
|
2015-04-27 13:48:39 -07:00
|
|
|
default:
|
|
|
|
|
MISSING_CASE(rotation);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 15:07:02 +01:00
|
|
|
return 0;
|
2015-04-27 13:48:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void skylake_update_primary_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);
|
2015-04-21 17:12:53 +03:00
|
|
|
struct drm_plane *plane = crtc->primary;
|
|
|
|
|
bool visible = to_intel_plane_state(plane->state)->visible;
|
2015-04-27 13:48:39 -07:00
|
|
|
struct drm_i915_gem_object *obj;
|
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
u32 plane_ctl, stride_div, stride;
|
|
|
|
|
u32 tile_height, plane_offset, plane_size;
|
|
|
|
|
unsigned int rotation;
|
|
|
|
|
int x_offset, y_offset;
|
2015-10-30 13:26:15 +02:00
|
|
|
u32 surf_addr;
|
2015-04-27 13:48:39 -07:00
|
|
|
struct intel_crtc_state *crtc_state = intel_crtc->config;
|
|
|
|
|
struct intel_plane_state *plane_state;
|
|
|
|
|
int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
|
|
|
|
|
int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
|
|
|
|
|
int scaler_id = -1;
|
|
|
|
|
|
|
|
|
|
plane_state = to_intel_plane_state(plane->state);
|
|
|
|
|
|
2015-04-21 17:12:53 +03:00
|
|
|
if (!visible || !fb) {
|
2015-04-27 13:48:39 -07:00
|
|
|
I915_WRITE(PLANE_CTL(pipe, 0), 0);
|
|
|
|
|
I915_WRITE(PLANE_SURF(pipe, 0), 0);
|
|
|
|
|
POSTING_READ(PLANE_CTL(pipe, 0));
|
|
|
|
|
return;
|
2015-04-10 14:37:29 +05:30
|
|
|
}
|
2013-07-03 21:06:04 +01:00
|
|
|
|
2015-04-27 13:48:39 -07:00
|
|
|
plane_ctl = PLANE_CTL_ENABLE |
|
|
|
|
|
PLANE_CTL_PIPE_GAMMA_ENABLE |
|
|
|
|
|
PLANE_CTL_PIPE_CSC_ENABLE;
|
|
|
|
|
|
|
|
|
|
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
|
|
|
|
|
plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
|
|
|
|
|
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
|
|
|
|
|
|
|
|
|
|
rotation = plane->state->rotation;
|
|
|
|
|
plane_ctl |= skl_plane_ctl_rotation(rotation);
|
|
|
|
|
|
2015-02-27 11:15:18 +00:00
|
|
|
obj = intel_fb_obj(fb);
|
|
|
|
|
stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
|
|
fb->pixel_format);
|
2015-09-21 10:45:35 +01:00
|
|
|
surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
|
2015-04-10 14:37:29 +05:30
|
|
|
|
2015-09-30 17:05:43 -03:00
|
|
|
WARN_ON(drm_rect_width(&plane_state->src) == 0);
|
|
|
|
|
|
|
|
|
|
scaler_id = plane_state->scaler_id;
|
|
|
|
|
src_x = plane_state->src.x1 >> 16;
|
|
|
|
|
src_y = plane_state->src.y1 >> 16;
|
|
|
|
|
src_w = drm_rect_width(&plane_state->src) >> 16;
|
|
|
|
|
src_h = drm_rect_height(&plane_state->src) >> 16;
|
|
|
|
|
dst_x = plane_state->dst.x1;
|
|
|
|
|
dst_y = plane_state->dst.y1;
|
|
|
|
|
dst_w = drm_rect_width(&plane_state->dst);
|
|
|
|
|
dst_h = drm_rect_height(&plane_state->dst);
|
|
|
|
|
|
|
|
|
|
WARN_ON(x != src_x || y != src_y);
|
2015-04-27 13:48:39 -07:00
|
|
|
|
2015-04-10 14:37:29 +05:30
|
|
|
if (intel_rotation_90_or_270(rotation)) {
|
|
|
|
|
/* stride = Surface height in tiles */
|
2015-05-08 20:22:46 -07:00
|
|
|
tile_height = intel_tile_height(dev, fb->pixel_format,
|
2015-09-21 10:45:32 +01:00
|
|
|
fb->modifier[0], 0);
|
2015-04-10 14:37:29 +05:30
|
|
|
stride = DIV_ROUND_UP(fb->height, tile_height);
|
2015-04-27 13:48:39 -07:00
|
|
|
x_offset = stride * tile_height - y - src_h;
|
2015-04-10 14:37:29 +05:30
|
|
|
y_offset = x;
|
2015-04-27 13:48:39 -07:00
|
|
|
plane_size = (src_w - 1) << 16 | (src_h - 1);
|
2015-04-10 14:37:29 +05:30
|
|
|
} else {
|
|
|
|
|
stride = fb->pitches[0] / stride_div;
|
|
|
|
|
x_offset = x;
|
|
|
|
|
y_offset = y;
|
2015-04-27 13:48:39 -07:00
|
|
|
plane_size = (src_h - 1) << 16 | (src_w - 1);
|
2015-04-10 14:37:29 +05:30
|
|
|
}
|
|
|
|
|
plane_offset = y_offset << 16 | x_offset;
|
2015-02-27 11:15:18 +00:00
|
|
|
|
2015-09-14 15:20:03 -03:00
|
|
|
intel_crtc->adjusted_x = x_offset;
|
|
|
|
|
intel_crtc->adjusted_y = y_offset;
|
|
|
|
|
|
2013-07-03 21:06:04 +01:00
|
|
|
I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
|
2015-04-10 14:37:29 +05:30
|
|
|
I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
|
|
|
|
|
I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
|
|
|
|
|
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
|
2015-04-27 13:48:39 -07:00
|
|
|
|
|
|
|
|
if (scaler_id >= 0) {
|
|
|
|
|
uint32_t ps_ctrl = 0;
|
|
|
|
|
|
|
|
|
|
WARN_ON(!dst_w || !dst_h);
|
|
|
|
|
ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(0) |
|
|
|
|
|
crtc_state->scaler_state.scalers[scaler_id].mode;
|
|
|
|
|
I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
|
|
|
|
|
I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (dst_x << 16) | dst_y);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), (dst_w << 16) | dst_h);
|
|
|
|
|
I915_WRITE(PLANE_POS(pipe, 0), 0);
|
|
|
|
|
} else {
|
|
|
|
|
I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-23 11:10:37 +00:00
|
|
|
I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
|
2013-07-03 21:06:04 +01:00
|
|
|
|
|
|
|
|
POSTING_READ(PLANE_SURF(pipe, 0));
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 12:19:23 -07:00
|
|
|
/* 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;
|
|
|
|
|
|
2015-10-14 17:45:36 -03:00
|
|
|
if (dev_priv->fbc.deactivate)
|
|
|
|
|
dev_priv->fbc.deactivate(dev_priv);
|
2010-08-02 12:07:50 -07:00
|
|
|
|
2014-04-24 23:55:01 +02:00
|
|
|
dev_priv->display.update_primary_plane(crtc, fb, x, y);
|
|
|
|
|
|
|
|
|
|
return 0;
|
2010-08-02 12:07:50 -07:00
|
|
|
}
|
|
|
|
|
|
2014-11-24 18:28:11 +02:00
|
|
|
static void intel_complete_page_flips(struct drm_device *dev)
|
2013-02-18 19:08:49 +02:00
|
|
|
{
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
|
2014-05-13 23:32:24 +01:00
|
|
|
for_each_crtc(dev, crtc) {
|
2013-02-18 19:08:49 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2014-11-24 18:28:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_update_primary_planes(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_crtc *crtc;
|
2013-02-18 19:08:49 +02:00
|
|
|
|
2014-05-13 23:32:24 +01:00
|
|
|
for_each_crtc(dev, crtc) {
|
2015-09-10 16:07:58 +02:00
|
|
|
struct intel_plane *plane = to_intel_plane(crtc->primary);
|
|
|
|
|
struct intel_plane_state *plane_state;
|
2013-02-18 19:08:49 +02:00
|
|
|
|
2015-09-10 16:07:58 +02:00
|
|
|
drm_modeset_lock_crtc(crtc, &plane->base);
|
|
|
|
|
plane_state = to_intel_plane_state(plane->base.state);
|
|
|
|
|
|
2015-09-23 16:29:37 +02:00
|
|
|
if (crtc->state->active && plane_state->base.fb)
|
2015-09-10 16:07:58 +02:00
|
|
|
plane->commit_plane(&plane->base, plane_state);
|
|
|
|
|
|
|
|
|
|
drm_modeset_unlock_crtc(crtc);
|
2013-02-18 19:08:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-24 18:28:11 +02:00
|
|
|
void intel_prepare_reset(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
/* no reset support for gen2 */
|
|
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* reset doesn't touch the display */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
drm_modeset_lock_all(dev);
|
2014-11-21 21:54:30 +02:00
|
|
|
/*
|
|
|
|
|
* Disabling the crtcs gracefully seems nicer. Also the
|
|
|
|
|
* g33 docs say we should at least disable all the planes.
|
|
|
|
|
*/
|
2015-06-01 12:49:47 +02:00
|
|
|
intel_display_suspend(dev);
|
2014-11-24 18:28:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_finish_reset(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Flips in the rings will be nuked by the reset,
|
|
|
|
|
* so complete all pending flips so that user space
|
|
|
|
|
* will get its events and not get stuck.
|
|
|
|
|
*/
|
|
|
|
|
intel_complete_page_flips(dev);
|
|
|
|
|
|
|
|
|
|
/* no reset support for gen2 */
|
|
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* reset doesn't touch the display */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
|
|
|
|
|
/*
|
|
|
|
|
* Flips in the rings have been nuked by the reset,
|
|
|
|
|
* so 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.
|
2015-09-10 16:07:58 +02:00
|
|
|
*
|
|
|
|
|
* FIXME: Atomic will make this obsolete since we won't schedule
|
|
|
|
|
* CS-based flips (which might get lost in gpu resets) any more.
|
2014-11-24 18:28:11 +02:00
|
|
|
*/
|
|
|
|
|
intel_update_primary_planes(dev);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The display has been reset as well,
|
|
|
|
|
* so need a full re-initialization.
|
|
|
|
|
*/
|
|
|
|
|
intel_runtime_pm_disable_interrupts(dev_priv);
|
|
|
|
|
intel_runtime_pm_enable_interrupts(dev_priv);
|
|
|
|
|
|
|
|
|
|
intel_modeset_init_hw(dev);
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&dev_priv->irq_lock);
|
|
|
|
|
if (dev_priv->display.hpd_irq_setup)
|
|
|
|
|
dev_priv->display.hpd_irq_setup(dev);
|
|
|
|
|
spin_unlock_irq(&dev_priv->irq_lock);
|
|
|
|
|
|
2015-07-13 16:30:25 +02:00
|
|
|
intel_display_resume(dev);
|
2014-11-24 18:28:11 +02:00
|
|
|
|
|
|
|
|
intel_hpd_init(dev_priv);
|
|
|
|
|
|
|
|
|
|
drm_modeset_unlock_all(dev);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-04 13:15:08 +00: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;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
bool pending;
|
|
|
|
|
|
|
|
|
|
if (i915_reset_in_progress(&dev_priv->gpu_error) ||
|
|
|
|
|
intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
|
|
|
|
|
return false;
|
|
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2014-03-04 13:15:08 +00:00
|
|
|
pending = to_intel_crtc(crtc)->unpin_work != NULL;
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2014-03-04 13:15:08 +00:00
|
|
|
|
|
|
|
|
return pending;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
static void intel_update_pipe_config(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *old_crtc_state)
|
2014-09-10 12:04:17 -03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-08-27 15:44:05 +02:00
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
2014-09-10 12:04:17 -03:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
/* drm_atomic_helper_update_legacy_modeset_state might not be called. */
|
|
|
|
|
crtc->base.mode = crtc->base.state->mode;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n",
|
|
|
|
|
old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h,
|
|
|
|
|
pipe_config->pipe_src_w, pipe_config->pipe_src_h);
|
2014-09-10 12:04:17 -03:00
|
|
|
|
2015-08-27 15:44:02 +02:00
|
|
|
if (HAS_DDI(dev))
|
|
|
|
|
intel_set_pipe_csc(&crtc->base);
|
|
|
|
|
|
2014-09-10 12:04:17 -03:00
|
|
|
/*
|
|
|
|
|
* Update pipe size and adjust fitter if needed: the reason for this is
|
|
|
|
|
* that in compute_mode_changes we check the native mode (not the pfit
|
|
|
|
|
* mode) to see if we can flip rather than do a full mode set. In the
|
|
|
|
|
* fastboot case, we'll flip, but if we don't update the pipesrc and
|
|
|
|
|
* pfit state, we'll end up with a big fb scanned out into the wrong
|
|
|
|
|
* sized surface.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
I915_WRITE(PIPESRC(crtc->pipe),
|
2015-08-27 15:44:05 +02:00
|
|
|
((pipe_config->pipe_src_w - 1) << 16) |
|
|
|
|
|
(pipe_config->pipe_src_h - 1));
|
|
|
|
|
|
|
|
|
|
/* on skylake this is done by detaching scalers */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
skl_detach_scalers(crtc);
|
|
|
|
|
|
|
|
|
|
if (pipe_config->pch_pfit.enabled)
|
|
|
|
|
skylake_pfit_enable(crtc);
|
|
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
|
|
|
|
if (pipe_config->pch_pfit.enabled)
|
|
|
|
|
ironlake_pfit_enable(crtc);
|
|
|
|
|
else if (old_crtc_state->pch_pfit.enabled)
|
|
|
|
|
ironlake_pfit_disable(crtc, true);
|
2014-09-10 12:04:17 -03: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp;
|
2010-10-28 16:38:08 +08:00
|
|
|
|
|
|
|
|
/* enable normal train */
|
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2011-05-17 16:13:52 -07:00
|
|
|
if (IS_IVYBRIDGE(dev)) {
|
2011-04-28 15:09:55 -07:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE_IVB;
|
|
|
|
|
temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
|
2011-05-17 16:13:52 -07:00
|
|
|
} else {
|
|
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
|
|
|
temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
|
2011-04-28 15:09:55 -07: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-28 15:09:55 -07: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
|
|
|
}
|
|
|
|
|
|
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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp, tries;
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2014-04-25 22:12:07 +03:00
|
|
|
/* FDI needs bits from pipe first */
|
2011-01-04 15:09:37 -08:00
|
|
|
assert_pipe_enabled(dev_priv, pipe);
|
|
|
|
|
|
2010-06-25 15:32:14 -04:00
|
|
|
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
|
|
for train result */
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_RX_IMR(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2010-06-25 15:32:14 -04:00
|
|
|
temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
|
|
temp &= ~FDI_RX_BIT_LOCK;
|
2010-09-11 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
I915_READ(reg);
|
2010-06-25 15:32:14 -04:00
|
|
|
udelay(150);
|
|
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2013-04-29 19:33:42 +02:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
2015-01-15 14:55:25 +02:00
|
|
|
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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
|
2010-10-07 16:01:15 -07:00
|
|
|
/* Ironlake workaround, enable clock pointer after FDI enable*/
|
2012-10-31 22:52:28 +01: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-07 16:01:15 -07:00
|
|
|
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_RX_IIR(pipe);
|
2010-06-25 15:32:14 -04:00
|
|
|
for (tries = 0; tries < 5; tries++) {
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
|
2010-04-07 16:15:54 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-25 15:32:14 -04:00
|
|
|
if (tries == 5)
|
2010-09-11 13:48:45 +01:00
|
|
|
DRM_ERROR("FDI train 1 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
|
/* Train 2 */
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 13:48:45 +01:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(150);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_RX_IIR(pipe);
|
2010-06-25 15:32:14 -04:00
|
|
|
for (tries = 0; tries < 5; tries++) {
|
2010-09-11 13:48:45 +01: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 13:48:45 +01: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-25 15:32:14 -04:00
|
|
|
if (tries == 5)
|
2010-09-11 13:48:45 +01: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-07 16:01:11 -07:00
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
|
|
2011-08-16 15:34:10 -04: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp, i, retry;
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-06-25 15:32:14 -04:00
|
|
|
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
|
|
|
for train result */
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_RX_IMR(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2010-06-25 15:32:14 -04:00
|
|
|
temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
|
|
|
temp &= ~FDI_RX_BIT_LOCK;
|
2010-09-11 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-06-25 15:32:14 -04:00
|
|
|
udelay(150);
|
|
|
|
|
|
2010-04-07 16:15:54 +08:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2013-04-29 19:33:42 +02:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
2015-01-15 14:55:25 +02:00
|
|
|
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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2012-10-26 10:58:13 +02:00
|
|
|
I915_WRITE(FDI_RX_MISC(pipe),
|
|
|
|
|
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
|
|
|
|
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
|
2011-08-16 15:34:10 -04:00
|
|
|
for (i = 0; i < 4; i++) {
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(500);
|
|
|
|
|
|
2012-03-02 12:53:39 -05: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-02 12:53:39 -05:00
|
|
|
if (retry < 5)
|
|
|
|
|
break;
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
|
if (i == 4)
|
2010-09-11 13:48:45 +01:00
|
|
|
DRM_ERROR("FDI train 1 fail!\n");
|
2010-04-07 16:15:54 +08:00
|
|
|
|
|
|
|
|
/* Train 2 */
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(150);
|
|
|
|
|
|
2011-08-16 15:34:10 -04:00
|
|
|
for (i = 0; i < 4; i++) {
|
2010-09-11 13:48:45 +01: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 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-04-07 16:15:54 +08:00
|
|
|
udelay(500);
|
|
|
|
|
|
2012-03-02 12:53:39 -05: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-02 12:53:39 -05:00
|
|
|
if (retry < 5)
|
|
|
|
|
break;
|
2010-04-07 16:15:54 +08:00
|
|
|
}
|
|
|
|
|
if (i == 4)
|
2010-09-11 13:48:45 +01: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-28 15:09:55 -07: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp, i, j;
|
2011-04-28 15:09:55 -07:00
|
|
|
|
|
|
|
|
/* 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 15:58:40 +02:00
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
|
|
|
|
|
I915_READ(FDI_RX_IIR(pipe)));
|
|
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
/* Try each vswing and preemphasis setting twice before moving on */
|
|
|
|
|
for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) {
|
|
|
|
|
/* disable first in case we need to retry */
|
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
|
|
|
|
|
temp &= ~FDI_TX_ENABLE;
|
|
|
|
|
I915_WRITE(reg, temp);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
temp &= ~FDI_LINK_TRAIN_AUTO;
|
|
|
|
|
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
|
|
|
temp &= ~FDI_RX_ENABLE;
|
|
|
|
|
I915_WRITE(reg, temp);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
/* enable CPU FDI TX and PCH FDI RX */
|
2011-04-28 15:09:55 -07:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2013-08-19 11:04:55 -07:00
|
|
|
temp &= ~FDI_DP_PORT_WIDTH_MASK;
|
2015-01-15 14:55:25 +02:00
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
|
2013-08-19 11:04:55 -07:00
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
|
2011-04-28 15:09:55 -07:00
|
|
|
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
2013-08-19 11:04:55 -07:00
|
|
|
temp |= snb_b_fdi_train_param[j/2];
|
|
|
|
|
temp |= FDI_COMPOSITE_SYNC;
|
|
|
|
|
I915_WRITE(reg, temp | FDI_TX_ENABLE);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
I915_WRITE(FDI_RX_MISC(pipe),
|
|
|
|
|
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
2011-04-28 15:09:55 -07:00
|
|
|
temp = I915_READ(reg);
|
2013-08-19 11:04:55 -07:00
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
|
|
|
|
temp |= FDI_COMPOSITE_SYNC;
|
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_ENABLE);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(1); /* should be 0.5us */
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
if (temp & FDI_RX_BIT_LOCK ||
|
|
|
|
|
(I915_READ(reg) & FDI_RX_BIT_LOCK)) {
|
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
|
|
|
|
|
DRM_DEBUG_KMS("FDI train 1 done, level %i.\n",
|
|
|
|
|
i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
udelay(1); /* should be 0.5us */
|
|
|
|
|
}
|
|
|
|
|
if (i == 4) {
|
|
|
|
|
DRM_DEBUG_KMS("FDI train 1 fail on vswing %d\n", j / 2);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
/* Train 2 */
|
2011-04-28 15:09:55 -07:00
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2013-08-19 11:04:55 -07:00
|
|
|
temp &= ~FDI_LINK_TRAIN_NONE_IVB;
|
|
|
|
|
temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
|
|
|
|
|
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;
|
2011-04-28 15:09:55 -07:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2013-08-19 11:04:55 -07:00
|
|
|
udelay(2); /* should be 1.5us */
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
reg = FDI_RX_IIR(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
2011-04-28 15:09:55 -07:00
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
if (temp & FDI_RX_SYMBOL_LOCK ||
|
|
|
|
|
(I915_READ(reg) & FDI_RX_SYMBOL_LOCK)) {
|
|
|
|
|
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
|
|
|
|
|
DRM_DEBUG_KMS("FDI train 2 done, level %i.\n",
|
|
|
|
|
i);
|
|
|
|
|
goto train_done;
|
|
|
|
|
}
|
|
|
|
|
udelay(2); /* should be 1.5us */
|
2011-04-28 15:09:55 -07:00
|
|
|
}
|
2013-08-19 11:04:55 -07:00
|
|
|
if (i == 4)
|
|
|
|
|
DRM_DEBUG_KMS("FDI train 2 fail on vswing %d\n", j / 2);
|
2011-04-28 15:09:55 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-19 11:04:55 -07:00
|
|
|
train_done:
|
2011-04-28 15:09:55 -07:00
|
|
|
DRM_DEBUG_KMS("FDI train done.\n");
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-12 19:27:14 +02:00
|
|
|
static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2012-08-12 19:27:14 +02: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp;
|
2010-09-10 11:27:03 -07:00
|
|
|
|
2010-09-10 10:57:18 -07:00
|
|
|
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
2010-09-11 13:48:45 +01:00
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
2013-04-29 19:33:42 +02:00
|
|
|
temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
|
2015-01-15 14:55:25 +02:00
|
|
|
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config->fdi_lanes);
|
2012-12-17 11:21:38 +01:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2010-09-11 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-09-10 10:57:18 -07:00
|
|
|
udelay(200);
|
|
|
|
|
|
|
|
|
|
/* Switch from Rawclk to PCDclk */
|
2010-09-11 13:48:45 +01:00
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
I915_WRITE(reg, temp | FDI_PCDCLK);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
2010-09-10 10:57:18 -07:00
|
|
|
udelay(200);
|
|
|
|
|
|
2012-11-23 15:30:38 -02: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 13:48:45 +01:00
|
|
|
|
2012-11-23 15:30:38 -02:00
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(100);
|
2010-09-10 10:26:01 -07:00
|
|
|
}
|
2010-09-10 11:10:00 -07:00
|
|
|
}
|
|
|
|
|
|
2012-08-12 19:27:14 +02: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp;
|
2012-08-12 19:27:14 +02:00
|
|
|
|
|
|
|
|
/* 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-04 15: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp;
|
2011-01-04 15:09:37 -08:00
|
|
|
|
|
|
|
|
/* 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 11:21:38 +01:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2011-01-04 15:09:37 -08:00
|
|
|
I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(100);
|
|
|
|
|
|
|
|
|
|
/* Ironlake workaround, disable clock pointer after downing FDI */
|
2014-05-18 02:24:50 +02:00
|
|
|
if (HAS_PCH_IBX(dev))
|
2011-01-04 15:09:38 -08:00
|
|
|
I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
|
2011-01-04 15: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 11:21:38 +01:00
|
|
|
temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
2011-01-04 15:09:37 -08:00
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
POSTING_READ(reg);
|
|
|
|
|
udelay(100);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-20 10:17:36 +00:00
|
|
|
bool intel_has_pending_fb_unpin(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
|
|
/* Note that we don't need to be called with mode_config.lock here
|
|
|
|
|
* as our list of CRTC objects is static for the lifetime of the
|
|
|
|
|
* device and so cannot disappear as we iterate. Similarly, we can
|
|
|
|
|
* happily treat the predicates as racy, atomic checks as userspace
|
|
|
|
|
* cannot claim and pin a new fb without at least acquring the
|
|
|
|
|
* struct_mutex and so serialising with us.
|
|
|
|
|
*/
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2014-01-20 10:17:36 +00:00
|
|
|
if (atomic_read(&crtc->unpin_work_count) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (crtc->unpin_work)
|
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
static void page_flip_completed(struct intel_crtc *intel_crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
|
|
|
|
|
struct intel_unpin_work *work = intel_crtc->unpin_work;
|
|
|
|
|
|
|
|
|
|
/* ensure that the unpin work is consistent wrt ->pending. */
|
|
|
|
|
smp_rmb();
|
|
|
|
|
intel_crtc->unpin_work = NULL;
|
|
|
|
|
|
|
|
|
|
if (work->event)
|
|
|
|
|
drm_send_vblank_event(intel_crtc->base.dev,
|
|
|
|
|
intel_crtc->pipe,
|
|
|
|
|
work->event);
|
|
|
|
|
|
|
|
|
|
drm_crtc_vblank_put(&intel_crtc->base);
|
|
|
|
|
|
|
|
|
|
wake_up_all(&dev_priv->pending_flip_queue);
|
|
|
|
|
queue_work(dev_priv->wq, &work->work);
|
|
|
|
|
|
|
|
|
|
trace_i915_flip_complete(intel_crtc->plane,
|
|
|
|
|
work->pending_flip_obj);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
|
2010-09-23 23:04:43 +01:00
|
|
|
{
|
2012-04-17 10:05:38 +01:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2012-09-27 21:25:58 +01:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-08-18 13:40:05 +02:00
|
|
|
long ret;
|
2010-09-23 23:04:43 +01:00
|
|
|
|
2012-12-20 21:24:07 +01:00
|
|
|
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
|
2015-08-18 13:40:05 +02:00
|
|
|
|
|
|
|
|
ret = wait_event_interruptible_timeout(
|
|
|
|
|
dev_priv->pending_flip_queue,
|
|
|
|
|
!intel_crtc_has_pending_flip(crtc),
|
|
|
|
|
60*HZ);
|
|
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
2014-09-05 07:13:25 +01:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-12-20 21:24:07 +01:00
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2014-09-05 07:13:25 +01:00
|
|
|
if (intel_crtc->unpin_work) {
|
|
|
|
|
WARN_ONCE(1, "Removing stuck page flip\n");
|
|
|
|
|
page_flip_completed(intel_crtc);
|
|
|
|
|
}
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2014-09-05 07:13:25 +01:00
|
|
|
}
|
2012-09-27 21:25:58 +01:00
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
return 0;
|
2010-09-23 23:04:43 +01:00
|
|
|
}
|
|
|
|
|
|
2015-12-04 22:21:34 +02:00
|
|
|
static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
u32 temp;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
|
|
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
|
|
|
|
|
temp |= SBI_SSCCTL_DISABLE;
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
|
|
|
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-09 15:37:26 -03: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;
|
2015-01-15 14:55:25 +02:00
|
|
|
int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock;
|
2012-05-09 15:37:26 -03:00
|
|
|
u32 divsel, phaseinc, auxdiv, phasedir = 0;
|
|
|
|
|
u32 temp;
|
|
|
|
|
|
2015-12-04 22:21:34 +02:00
|
|
|
lpt_disable_iclkip(dev_priv);
|
2012-05-09 15:37:26 -03:00
|
|
|
|
|
|
|
|
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
|
2013-09-04 18:25:19 +03:00
|
|
|
if (clock == 20000) {
|
2012-05-09 15:37:26 -03:00
|
|
|
auxdiv = 1;
|
|
|
|
|
divsel = 0x41;
|
|
|
|
|
phaseinc = 0x20;
|
|
|
|
|
} else {
|
|
|
|
|
/* The iCLK virtual clock root frequency is in MHz,
|
2013-09-25 16:45:37 +01:00
|
|
|
* but the adjusted_mode->crtc_clock in in KHz. To get the
|
|
|
|
|
* divisors, it is necessary to divide one by another, so we
|
2012-05-09 15:37:26 -03:00
|
|
|
* 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;
|
|
|
|
|
|
2015-12-04 22:20:21 +02:00
|
|
|
desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
|
2012-05-09 15:37:26 -03:00
|
|
|
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",
|
2013-09-04 18:25:19 +03:00
|
|
|
clock,
|
2012-05-09 15:37:26 -03:00
|
|
|
auxdiv,
|
|
|
|
|
divsel,
|
|
|
|
|
phasedir,
|
|
|
|
|
phaseinc);
|
|
|
|
|
|
2015-12-04 22:21:34 +02:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
|
2012-05-09 15:37:26 -03:00
|
|
|
/* Program SSCDIVINTPHASE6 */
|
2012-12-01 12:04:24 -02:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
|
2012-05-09 15:37:26 -03: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 12:04:24 -02:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
|
2012-05-09 15:37:26 -03:00
|
|
|
|
|
|
|
|
/* Program SSCAUXDIV */
|
2012-12-01 12:04:24 -02:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
|
2012-05-09 15:37:26 -03:00
|
|
|
temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
|
|
|
|
|
temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
|
2012-12-01 12:04:24 -02:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
|
2012-05-09 15:37:26 -03:00
|
|
|
|
|
|
|
|
/* Enable modulator and associated divider */
|
2012-12-01 12:04:24 -02:00
|
|
|
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
|
2012-05-09 15:37:26 -03:00
|
|
|
temp &= ~SBI_SSCCTL_DISABLE;
|
2012-12-01 12:04:24 -02:00
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
|
2012-05-09 15:37:26 -03:00
|
|
|
|
2015-12-04 22:21:34 +02:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
|
2012-05-09 15:37:26 -03:00
|
|
|
/* Wait for initialization time */
|
|
|
|
|
udelay(24);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-03 11:49:47 +02: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;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
|
2013-05-03 11:49:47 +02:00
|
|
|
|
|
|
|
|
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)));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-11 13:35:43 +02:00
|
|
|
static void cpt_set_fdi_bc_bifurcation(struct drm_device *dev, bool enable)
|
2013-10-29 12:04:08 +01:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t temp;
|
|
|
|
|
|
|
|
|
|
temp = I915_READ(SOUTH_CHICKEN1);
|
2015-03-11 13:35:43 +02:00
|
|
|
if (!!(temp & FDI_BC_BIFURCATION_SELECT) == enable)
|
2013-10-29 12:04:08 +01:00
|
|
|
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);
|
|
|
|
|
|
2015-03-11 13:35:43 +02:00
|
|
|
temp &= ~FDI_BC_BIFURCATION_SELECT;
|
|
|
|
|
if (enable)
|
|
|
|
|
temp |= FDI_BC_BIFURCATION_SELECT;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("%sabling fdi C rx\n", enable ? "en" : "dis");
|
2013-10-29 12:04:08 +01:00
|
|
|
I915_WRITE(SOUTH_CHICKEN1, temp);
|
|
|
|
|
POSTING_READ(SOUTH_CHICKEN1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
|
|
|
|
|
switch (intel_crtc->pipe) {
|
|
|
|
|
case PIPE_A:
|
|
|
|
|
break;
|
|
|
|
|
case PIPE_B:
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->fdi_lanes > 2)
|
2015-03-11 13:35:43 +02:00
|
|
|
cpt_set_fdi_bc_bifurcation(dev, false);
|
2013-10-29 12:04:08 +01:00
|
|
|
else
|
2015-03-11 13:35:43 +02:00
|
|
|
cpt_set_fdi_bc_bifurcation(dev, true);
|
2013-10-29 12:04:08 +01:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case PIPE_C:
|
2015-03-11 13:35:43 +02:00
|
|
|
cpt_set_fdi_bc_bifurcation(dev, true);
|
2013-10-29 12:04:08 +01:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BUG();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-04 23:19:56 +02:00
|
|
|
/* Return which DP Port should be selected for Transcoder DP control */
|
|
|
|
|
static enum port
|
|
|
|
|
intel_trans_dp_port_sel(struct drm_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
|
if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
|
|
|
|
|
encoder->type == INTEL_OUTPUT_EDP)
|
|
|
|
|
return enc_to_dig_port(&encoder->base)->port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-05 10: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-10 11:10:00 -07: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
u32 temp;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
assert_pch_transcoder_disabled(dev_priv, pipe);
|
2012-05-11 09:21:25 +01:00
|
|
|
|
2013-10-29 12:04:08 +01:00
|
|
|
if (IS_IVYBRIDGE(dev))
|
|
|
|
|
ivybridge_update_fdi_bc_bifurcation(intel_crtc);
|
|
|
|
|
|
2012-10-26 10:58:12 +02: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);
|
|
|
|
|
|
2015-11-20 22:09:18 +02:00
|
|
|
/*
|
|
|
|
|
* Sometimes spurious CPU pipe underruns happen during FDI
|
|
|
|
|
* training, at least with VGA+HDMI cloning. Suppress them.
|
|
|
|
|
*/
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
|
|
|
2010-09-10 10:57:18 -07:00
|
|
|
/* For PCH output, training FDI link */
|
2011-04-28 14:27:04 -07:00
|
|
|
dev_priv->display.fdi_link_train(crtc);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-06-05 13:34:32 +02:00
|
|
|
/* We need to program the right clock selection before writing the pixel
|
|
|
|
|
* mutliplier into the DPLL. */
|
2012-10-31 18:12:23 -02:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
2012-04-20 17:11:53 +01:00
|
|
|
u32 sel;
|
2011-10-12 09:51:31 -07:00
|
|
|
|
2010-09-10 10:57:18 -07:00
|
|
|
temp = I915_READ(PCH_DPLL_SEL);
|
2013-06-05 13:34:09 +02:00
|
|
|
temp |= TRANS_DPLL_ENABLE(pipe);
|
|
|
|
|
sel = TRANS_DPLLB_SEL(pipe);
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->shared_dpll == DPLL_ID_PCH_PLL_B)
|
2012-04-20 17:11:53 +01:00
|
|
|
temp |= sel;
|
|
|
|
|
else
|
|
|
|
|
temp &= ~sel;
|
2010-09-10 10:57:18 -07:00
|
|
|
I915_WRITE(PCH_DPLL_SEL, temp);
|
|
|
|
|
}
|
2010-09-11 13:48:45 +01:00
|
|
|
|
2013-06-05 13:34:32 +02: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_shared_dpll tries to do the right thing, but
|
|
|
|
|
* get_shared_dpll unconditionally resets the pll - we need that to have
|
|
|
|
|
* the right LVDS enable sequence. */
|
2014-04-24 23:55:14 +02:00
|
|
|
intel_enable_shared_dpll(intel_crtc);
|
2013-06-05 13:34:32 +02:00
|
|
|
|
2011-01-04 15:09:35 -08:00
|
|
|
/* set transcoder timing, panel must allow it */
|
|
|
|
|
assert_panel_unlocked(dev_priv, pipe);
|
2013-05-03 11:49:47 +02:00
|
|
|
ironlake_pch_transcoder_set_timings(intel_crtc, pipe);
|
2010-04-07 16:15:54 +08:00
|
|
|
|
2012-10-31 18:12:23 -02:00
|
|
|
intel_fdi_normal_train(crtc);
|
2010-10-28 16:38:08 +08:00
|
|
|
|
2015-11-20 22:09:18 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
|
2010-09-10 10:57:18 -07:00
|
|
|
/* For PCH DP, enable TRANS_DP_CTL */
|
2015-01-15 14:55:25 +02:00
|
|
|
if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) {
|
2015-10-29 21:25:51 +02:00
|
|
|
const struct drm_display_mode *adjusted_mode =
|
|
|
|
|
&intel_crtc->config->base.adjusted_mode;
|
2012-12-17 11:21:38 +01:00
|
|
|
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = TRANS_DP_CTL(pipe);
|
2010-09-11 13:48:45 +01:00
|
|
|
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);
|
2015-05-05 17:17:31 +03:00
|
|
|
temp |= TRANS_DP_OUTPUT_ENABLE;
|
2011-06-24 12:19:21 -07:00
|
|
|
temp |= bpc << 9; /* same format but at 11:9 */
|
2010-09-10 10:57:18 -07:00
|
|
|
|
2015-10-29 21:25:51 +02:00
|
|
|
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
2010-09-11 13:48:45 +01:00
|
|
|
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
|
2015-10-29 21:25:51 +02:00
|
|
|
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
2010-09-11 13:48:45 +01:00
|
|
|
temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
|
2010-09-10 10:57:18 -07:00
|
|
|
|
|
|
|
|
switch (intel_trans_dp_port_sel(crtc)) {
|
2015-11-04 23:19:56 +02:00
|
|
|
case PORT_B:
|
2010-09-11 13:48:45 +01:00
|
|
|
temp |= TRANS_DP_PORT_SEL_B;
|
2010-09-10 10:57:18 -07:00
|
|
|
break;
|
2015-11-04 23:19:56 +02:00
|
|
|
case PORT_C:
|
2010-09-11 13:48:45 +01:00
|
|
|
temp |= TRANS_DP_PORT_SEL_C;
|
2010-09-10 10:57:18 -07:00
|
|
|
break;
|
2015-11-04 23:19:56 +02:00
|
|
|
case PORT_D:
|
2010-09-11 13:48:45 +01:00
|
|
|
temp |= TRANS_DP_PORT_SEL_D;
|
2010-09-10 10:57:18 -07:00
|
|
|
break;
|
|
|
|
|
default:
|
2012-10-26 10:58:16 +02:00
|
|
|
BUG();
|
2009-07-24 01:00:32 +08:00
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2010-09-11 13:48:45 +01:00
|
|
|
I915_WRITE(reg, temp);
|
2010-09-10 10:26:01 -07:00
|
|
|
}
|
2010-06-12 14:32:27 +08:00
|
|
|
|
2012-10-31 18:12:42 -02:00
|
|
|
ironlake_enable_pch_transcoder(dev_priv, pipe);
|
2011-01-05 10:31:48 -08:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 18:12:22 -02: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);
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
2012-10-31 18:12:22 -02:00
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
assert_pch_transcoder_disabled(dev_priv, TRANSCODER_A);
|
2012-10-31 18:12:22 -02:00
|
|
|
|
2012-10-31 18:12:24 -02:00
|
|
|
lpt_program_iclkip(crtc);
|
2012-10-31 18:12:22 -02:00
|
|
|
|
2012-10-31 18:12:40 -02:00
|
|
|
/* Set transcoder timing. */
|
2013-05-03 11:49:47 +02:00
|
|
|
ironlake_pch_transcoder_set_timings(intel_crtc, PIPE_A);
|
2012-10-31 18:12:22 -02:00
|
|
|
|
2012-10-31 18:12:47 -02:00
|
|
|
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
|
2011-01-05 10:31:48 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2013-06-07 23:10:03 +02:00
|
|
|
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
2014-10-29 11:32:33 +02:00
|
|
|
struct intel_shared_dpll *pll;
|
2015-06-04 10:21:28 +02:00
|
|
|
struct intel_shared_dpll_config *shared_dpll;
|
2013-06-07 23:10:03 +02:00
|
|
|
enum intel_dpll_id i;
|
2015-11-16 14:42:12 +01:00
|
|
|
int max = dev_priv->num_shared_dpll;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
|
|
|
|
|
|
2012-05-20 20:00:25 +02:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
|
|
/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
|
2013-07-04 12:01:16 +02:00
|
|
|
i = (enum intel_dpll_id) crtc->pipe;
|
2013-06-05 13:34:06 +02:00
|
|
|
pll = &dev_priv->shared_dplls[i];
|
2012-05-20 20:00:25 +02:00
|
|
|
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
|
|
|
|
|
crtc->base.base.id, pll->name);
|
2012-05-20 20:00:25 +02:00
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
WARN_ON(shared_dpll[i].crtc_mask);
|
2014-05-20 15:19:19 +02:00
|
|
|
|
2012-05-20 20:00:25 +02:00
|
|
|
goto found;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-22 09:49:10 +05:30
|
|
|
if (IS_BROXTON(dev_priv->dev)) {
|
|
|
|
|
/* PLL is attached to port in bxt */
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
struct intel_digital_port *intel_dig_port;
|
|
|
|
|
|
|
|
|
|
encoder = intel_ddi_get_crtc_new_encoder(crtc_state);
|
|
|
|
|
if (WARN_ON(!encoder))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
intel_dig_port = enc_to_dig_port(&encoder->base);
|
|
|
|
|
/* 1:1 mapping between ports and PLLs */
|
|
|
|
|
i = (enum intel_dpll_id)intel_dig_port->port;
|
|
|
|
|
pll = &dev_priv->shared_dplls[i];
|
|
|
|
|
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
|
|
|
|
|
crtc->base.base.id, pll->name);
|
2015-06-04 10:21:28 +02:00
|
|
|
WARN_ON(shared_dpll[i].crtc_mask);
|
2014-08-22 09:49:10 +05:30
|
|
|
|
|
|
|
|
goto found;
|
2015-11-16 14:42:12 +01:00
|
|
|
} else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
|
|
|
|
|
/* Do not consider SPLL */
|
|
|
|
|
max = 2;
|
2014-08-22 09:49:10 +05:30
|
|
|
|
2015-11-16 14:42:12 +01:00
|
|
|
for (i = 0; i < max; i++) {
|
2013-06-05 13:34:06 +02:00
|
|
|
pll = &dev_priv->shared_dplls[i];
|
2012-04-20 17:11:53 +01:00
|
|
|
|
|
|
|
|
/* Only want to check enabled timings first */
|
2015-06-04 10:21:28 +02:00
|
|
|
if (shared_dpll[i].crtc_mask == 0)
|
2012-04-20 17:11:53 +01:00
|
|
|
continue;
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
if (memcmp(&crtc_state->dpll_hw_state,
|
2015-06-04 10:21:28 +02:00
|
|
|
&shared_dpll[i].hw_state,
|
|
|
|
|
sizeof(crtc_state->dpll_hw_state)) == 0) {
|
2014-10-29 11:32:33 +02:00
|
|
|
DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
|
2014-10-29 11:32:31 +02:00
|
|
|
crtc->base.base.id, pll->name,
|
2015-06-04 10:21:28 +02:00
|
|
|
shared_dpll[i].crtc_mask,
|
2014-10-29 11:32:33 +02:00
|
|
|
pll->active);
|
2012-04-20 17:11:53 +01:00
|
|
|
goto found;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ok no matching timings, maybe there's a free one? */
|
2013-06-05 13:34:06 +02:00
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
|
|
pll = &dev_priv->shared_dplls[i];
|
2015-06-04 10:21:28 +02:00
|
|
|
if (shared_dpll[i].crtc_mask == 0) {
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
|
|
|
|
|
crtc->base.base.id, pll->name);
|
2012-04-20 17:11:53 +01:00
|
|
|
goto found;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
found:
|
2015-06-04 10:21:28 +02:00
|
|
|
if (shared_dpll[i].crtc_mask == 0)
|
|
|
|
|
shared_dpll[i].hw_state =
|
|
|
|
|
crtc_state->dpll_hw_state;
|
2014-05-20 15:19:19 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->shared_dpll = i;
|
2013-06-05 13:34:12 +02:00
|
|
|
DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
|
|
|
|
|
pipe_name(crtc->pipe));
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
|
2012-05-02 20:43:56 +01:00
|
|
|
|
2012-04-20 17:11:53 +01:00
|
|
|
return pll;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
static void intel_shared_dpll_commit(struct drm_atomic_state *state)
|
2014-10-29 11:32:33 +02:00
|
|
|
{
|
2015-06-04 10:21:28 +02:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
|
|
|
|
struct intel_shared_dpll_config *shared_dpll;
|
2014-10-29 11:32:33 +02:00
|
|
|
struct intel_shared_dpll *pll;
|
|
|
|
|
enum intel_dpll_id i;
|
|
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
if (!to_intel_atomic_state(state)->dpll_set)
|
|
|
|
|
return;
|
2014-10-29 11:32:33 +02:00
|
|
|
|
2015-06-04 10:21:28 +02:00
|
|
|
shared_dpll = to_intel_atomic_state(state)->shared_dpll;
|
2014-10-29 11:32:33 +02:00
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
|
|
pll = &dev_priv->shared_dplls[i];
|
2015-06-04 10:21:28 +02:00
|
|
|
pll->config = shared_dpll[i];
|
2014-10-29 11:32:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-03 11:49:50 +02:00
|
|
|
static void cpt_verify_modeset(struct drm_device *dev, int pipe)
|
2011-10-11 10:43:02 -07:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t dslreg = PIPEDSL(pipe);
|
2011-10-11 10:43:02 -07: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 17:48:49 +03:00
|
|
|
DRM_ERROR("mode set failed: pipe %c stuck\n", pipe_name(pipe));
|
2011-10-11 10:43:02 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-22 09:50:32 +02:00
|
|
|
static int
|
|
|
|
|
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
|
|
|
|
|
unsigned scaler_user, int *scaler_id, unsigned int rotation,
|
|
|
|
|
int src_w, int src_h, int dst_w, int dst_h)
|
2015-04-07 15:28:45 -07:00
|
|
|
{
|
2015-06-22 09:50:32 +02:00
|
|
|
struct intel_crtc_scaler_state *scaler_state =
|
|
|
|
|
&crtc_state->scaler_state;
|
|
|
|
|
struct intel_crtc *intel_crtc =
|
|
|
|
|
to_intel_crtc(crtc_state->base.crtc);
|
2015-04-07 15:28:45 -07:00
|
|
|
int need_scaling;
|
2015-04-27 13:48:39 -07:00
|
|
|
|
|
|
|
|
need_scaling = intel_rotation_90_or_270(rotation) ?
|
|
|
|
|
(src_h != dst_w || src_w != dst_h):
|
|
|
|
|
(src_w != dst_w || src_h != dst_h);
|
2015-04-07 15:28:45 -07:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* if plane is being disabled or scaler is no more required or force detach
|
|
|
|
|
* - free scaler binded to this plane/crtc
|
|
|
|
|
* - in order to do this, update crtc->scaler_usage
|
|
|
|
|
*
|
|
|
|
|
* Here scaler state in crtc_state is set free so that
|
|
|
|
|
* scaler can be assigned to other user. Actual register
|
|
|
|
|
* update to free the scaler is done in plane/panel-fit programming.
|
|
|
|
|
* For this purpose crtc/plane_state->scaler_id isn't reset here.
|
|
|
|
|
*/
|
2015-06-22 09:50:32 +02:00
|
|
|
if (force_detach || !need_scaling) {
|
2015-04-07 15:28:45 -07:00
|
|
|
if (*scaler_id >= 0) {
|
2015-06-22 09:50:32 +02:00
|
|
|
scaler_state->scaler_users &= ~(1 << scaler_user);
|
2015-04-07 15:28:45 -07:00
|
|
|
scaler_state->scalers[*scaler_id].in_use = 0;
|
|
|
|
|
|
2015-06-22 09:50:32 +02:00
|
|
|
DRM_DEBUG_KMS("scaler_user index %u.%u: "
|
|
|
|
|
"Staged freeing scaler id %d scaler_users = 0x%x\n",
|
|
|
|
|
intel_crtc->pipe, scaler_user, *scaler_id,
|
2015-04-07 15:28:45 -07:00
|
|
|
scaler_state->scaler_users);
|
|
|
|
|
*scaler_id = -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* range checks */
|
|
|
|
|
if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
|
|
|
|
|
dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
|
|
|
|
|
|
|
|
|
|
src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
|
|
|
|
|
dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H) {
|
2015-06-22 09:50:32 +02:00
|
|
|
DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u "
|
2015-04-07 15:28:45 -07:00
|
|
|
"size is out of scaler range\n",
|
2015-06-22 09:50:32 +02:00
|
|
|
intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h);
|
2015-04-07 15:28:45 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-22 09:50:32 +02:00
|
|
|
/* mark this plane as a scaler user in crtc_state */
|
|
|
|
|
scaler_state->scaler_users |= (1 << scaler_user);
|
|
|
|
|
DRM_DEBUG_KMS("scaler_user index %u.%u: "
|
|
|
|
|
"staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
|
|
|
|
|
intel_crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
|
|
|
|
|
scaler_state->scaler_users);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
|
|
|
|
|
*
|
|
|
|
|
* @state: crtc's scaler state
|
|
|
|
|
*
|
|
|
|
|
* Return
|
|
|
|
|
* 0 - scaler_usage updated successfully
|
|
|
|
|
* error - requested scaling cannot be supported or other error condition
|
|
|
|
|
*/
|
2015-07-13 16:30:15 +02:00
|
|
|
int skl_update_scaler_crtc(struct intel_crtc_state *state)
|
2015-06-22 09:50:32 +02:00
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
|
2015-09-08 13:40:49 +03:00
|
|
|
const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
|
2015-06-22 09:50:32 +02:00
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Updating scaler for [CRTC:%i] scaler_user index %u.%u\n",
|
|
|
|
|
intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
|
|
|
|
|
|
2015-07-13 16:30:15 +02:00
|
|
|
return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
|
2015-06-22 09:50:32 +02:00
|
|
|
&state->scaler_state.scaler_id, DRM_ROTATE_0,
|
|
|
|
|
state->pipe_src_w, state->pipe_src_h,
|
2015-09-25 16:38:56 +03:00
|
|
|
adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
|
2015-06-22 09:50:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* skl_update_scaler_plane - Stages update to scaler state for a given plane.
|
|
|
|
|
*
|
|
|
|
|
* @state: crtc's scaler state
|
|
|
|
|
* @plane_state: atomic plane state to update
|
|
|
|
|
*
|
|
|
|
|
* Return
|
|
|
|
|
* 0 - scaler_usage updated successfully
|
|
|
|
|
* error - requested scaling cannot be supported or other error condition
|
|
|
|
|
*/
|
2015-06-15 12:33:44 +02:00
|
|
|
static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
|
|
|
|
|
struct intel_plane_state *plane_state)
|
2015-06-22 09:50:32 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
2015-06-15 12:33:44 +02:00
|
|
|
struct intel_plane *intel_plane =
|
|
|
|
|
to_intel_plane(plane_state->base.plane);
|
2015-06-22 09:50:32 +02:00
|
|
|
struct drm_framebuffer *fb = plane_state->base.fb;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
bool force_detach = !fb || !plane_state->visible;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Updating scaler for [PLANE:%d] scaler_user index %u.%u\n",
|
|
|
|
|
intel_plane->base.base.id, intel_crtc->pipe,
|
|
|
|
|
drm_plane_index(&intel_plane->base));
|
|
|
|
|
|
|
|
|
|
ret = skl_update_scaler(crtc_state, force_detach,
|
|
|
|
|
drm_plane_index(&intel_plane->base),
|
|
|
|
|
&plane_state->scaler_id,
|
|
|
|
|
plane_state->base.rotation,
|
|
|
|
|
drm_rect_width(&plane_state->src) >> 16,
|
|
|
|
|
drm_rect_height(&plane_state->src) >> 16,
|
|
|
|
|
drm_rect_width(&plane_state->dst),
|
|
|
|
|
drm_rect_height(&plane_state->dst));
|
|
|
|
|
|
|
|
|
|
if (ret || plane_state->scaler_id < 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2015-04-07 15:28:45 -07:00
|
|
|
/* check colorkey */
|
2015-06-15 12:33:54 +02:00
|
|
|
if (plane_state->ckey.flags != I915_SET_COLORKEY_NONE) {
|
2015-06-22 09:50:32 +02:00
|
|
|
DRM_DEBUG_KMS("[PLANE:%d] scaling with color key not allowed",
|
2015-06-15 12:33:54 +02:00
|
|
|
intel_plane->base.base.id);
|
2015-04-07 15:28:45 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check src format */
|
2015-06-22 09:50:32 +02:00
|
|
|
switch (fb->pixel_format) {
|
|
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
|
|
case DRM_FORMAT_YVYU:
|
|
|
|
|
case DRM_FORMAT_UYVY:
|
|
|
|
|
case DRM_FORMAT_VYUY:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
DRM_DEBUG_KMS("[PLANE:%d] FB:%d unsupported scaling format 0x%x\n",
|
|
|
|
|
intel_plane->base.base.id, fb->base.id, fb->pixel_format);
|
|
|
|
|
return -EINVAL;
|
2015-04-07 15:28:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:15 +02:00
|
|
|
static void skylake_scaler_disable(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < crtc->num_scalers; i++)
|
|
|
|
|
skl_detach_scaler(crtc, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void skylake_pfit_enable(struct intel_crtc *crtc)
|
2014-11-13 17:51:47 +00:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = crtc->pipe;
|
2015-04-07 15:28:45 -07:00
|
|
|
struct intel_crtc_scaler_state *scaler_state =
|
|
|
|
|
&crtc->config->scaler_state;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->pch_pfit.enabled) {
|
2015-04-07 15:28:45 -07:00
|
|
|
int id;
|
|
|
|
|
|
|
|
|
|
if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
|
|
|
|
|
DRM_ERROR("Requesting pfit without getting a scaler first\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
id = scaler_state->scaler_id;
|
|
|
|
|
I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
|
|
|
|
|
PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
|
|
|
|
|
I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
|
2014-11-13 17:51:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-25 12:55:02 -07: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;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->pch_pfit.enabled) {
|
2013-04-25 12:55:02 -07: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);
|
2015-01-15 14:55:25 +02:00
|
|
|
I915_WRITE(PF_WIN_POS(pipe), crtc->config->pch_pfit.pos);
|
|
|
|
|
I915_WRITE(PF_WIN_SZ(pipe), crtc->config->pch_pfit.size);
|
2011-10-11 10:43:02 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-01 18:02:17 +03:00
|
|
|
void hsw_enable_ips(struct intel_crtc *crtc)
|
2013-09-24 13:52:55 -03:00
|
|
|
{
|
2014-04-15 21:41:35 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-09-24 13:52:55 -03:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (!crtc->config->ips_enabled)
|
2013-09-24 13:52:55 -03:00
|
|
|
return;
|
|
|
|
|
|
2014-04-15 21:41:35 +03:00
|
|
|
/* We can only enable IPS after we enable a plane and wait for a vblank */
|
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
|
|
2013-09-24 13:52:55 -03:00
|
|
|
assert_plane_enabled(dev_priv, crtc->plane);
|
2014-04-15 21:41:35 +03:00
|
|
|
if (IS_BROADWELL(dev)) {
|
2013-11-02 21:07:47 -07:00
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000));
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
/* Quoting Art Runyan: "its not safe to expect any particular
|
|
|
|
|
* value in IPS_CTL bit 31 after enabling IPS through the
|
2014-01-07 13:30:45 -08:00
|
|
|
* mailbox." Moreover, the mailbox may return a bogus state,
|
|
|
|
|
* so we need to just enable it and continue on.
|
2013-11-02 21:07:47 -07:00
|
|
|
*/
|
|
|
|
|
} else {
|
|
|
|
|
I915_WRITE(IPS_CTL, IPS_ENABLE);
|
|
|
|
|
/* The bit only becomes 1 in the next vblank, so this wait here
|
|
|
|
|
* is essentially intel_wait_for_vblank. If we don't have this
|
|
|
|
|
* and don't wait for vblanks until the end of crtc_enable, then
|
|
|
|
|
* the HW state readout code will complain that the expected
|
|
|
|
|
* IPS_CTL value is not the one we read. */
|
|
|
|
|
if (wait_for(I915_READ_NOTRACE(IPS_CTL) & IPS_ENABLE, 50))
|
|
|
|
|
DRM_ERROR("Timed out waiting for IPS enable\n");
|
|
|
|
|
}
|
2013-09-24 13:52:55 -03:00
|
|
|
}
|
|
|
|
|
|
2013-10-01 18:02:17 +03:00
|
|
|
void hsw_disable_ips(struct intel_crtc *crtc)
|
2013-09-24 13:52:55 -03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (!crtc->config->ips_enabled)
|
2013-09-24 13:52:55 -03:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
assert_plane_enabled(dev_priv, crtc->plane);
|
2014-04-10 14:32:41 -07:00
|
|
|
if (IS_BROADWELL(dev)) {
|
2013-11-02 21:07:47 -07:00
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
2014-04-10 14:32:41 -07:00
|
|
|
/* wait for pcode to finish disabling IPS, which may take up to 42ms */
|
|
|
|
|
if (wait_for((I915_READ(IPS_CTL) & IPS_ENABLE) == 0, 42))
|
|
|
|
|
DRM_ERROR("Timed out waiting for IPS disable\n");
|
2014-01-07 13:30:45 -08:00
|
|
|
} else {
|
2013-11-02 21:07:47 -07:00
|
|
|
I915_WRITE(IPS_CTL, 0);
|
2014-01-07 13:30:45 -08:00
|
|
|
POSTING_READ(IPS_CTL);
|
|
|
|
|
}
|
2013-09-24 13:52:55 -03:00
|
|
|
|
|
|
|
|
/* We need to wait for a vblank before we can disable the plane. */
|
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Loads the palette/gamma unit for the CRTC with the prepared values */
|
|
|
|
|
static 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);
|
|
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
|
|
|
|
int i;
|
|
|
|
|
bool reenable_ips = false;
|
|
|
|
|
|
|
|
|
|
/* The clocks have to be on to load the palette. */
|
2015-06-01 12:49:52 +02:00
|
|
|
if (!crtc->state->active)
|
2013-09-24 13:52:55 -03:00
|
|
|
return;
|
|
|
|
|
|
2015-01-16 00:55:16 -08:00
|
|
|
if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
|
2015-11-27 12:21:46 +02:00
|
|
|
if (intel_crtc->config->has_dsi_encoder)
|
2013-09-24 13:52:55 -03:00
|
|
|
assert_dsi_pll_enabled(dev_priv);
|
|
|
|
|
else
|
|
|
|
|
assert_pll_enabled(dev_priv, 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.
|
|
|
|
|
*/
|
2015-01-15 14:55:25 +02:00
|
|
|
if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
|
2013-09-24 13:52:55 -03:00
|
|
|
((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
|
|
|
|
|
GAMMA_MODE_MODE_SPLIT)) {
|
|
|
|
|
hsw_disable_ips(intel_crtc);
|
|
|
|
|
reenable_ips = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t palreg;
|
2015-09-18 20:03:28 +03:00
|
|
|
|
|
|
|
|
if (HAS_GMCH_DISPLAY(dev))
|
|
|
|
|
palreg = PALETTE(pipe, i);
|
|
|
|
|
else
|
|
|
|
|
palreg = LGC_PALETTE(pipe, i);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(palreg,
|
2013-09-24 13:52:55 -03:00
|
|
|
(intel_crtc->lut_r[i] << 16) |
|
|
|
|
|
(intel_crtc->lut_g[i] << 8) |
|
|
|
|
|
intel_crtc->lut_b[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reenable_ips)
|
|
|
|
|
hsw_enable_ips(intel_crtc);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:12:55 +03:00
|
|
|
static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
|
2014-05-08 19:23:13 +03:00
|
|
|
{
|
2015-04-21 17:12:55 +03:00
|
|
|
if (intel_crtc->overlay) {
|
2014-05-08 19:23:13 +03:00
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
dev_priv->mm.interruptible = false;
|
|
|
|
|
(void) intel_overlay_switch_off(intel_crtc->overlay);
|
|
|
|
|
dev_priv->mm.interruptible = true;
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Let userspace switch the overlay on again. In most cases userspace
|
|
|
|
|
* has to recompute where to put it anyway.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:12:54 +03:00
|
|
|
/**
|
|
|
|
|
* intel_post_enable_primary - Perform operations after enabling primary plane
|
|
|
|
|
* @crtc: the CRTC whose primary plane was just enabled
|
|
|
|
|
*
|
|
|
|
|
* Performs potentially sleeping operations that must be done after the primary
|
|
|
|
|
* plane is enabled, such as updating FBC and IPS. Note that this may be
|
|
|
|
|
* called due to an explicit primary plane update, or due to an implicit
|
|
|
|
|
* re-enable that is caused when a sprite plane is updated to no longer
|
|
|
|
|
* completely hide the primary plane.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
intel_post_enable_primary(struct drm_crtc *crtc)
|
2014-03-07 18:32:13 +02:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2015-04-21 17:12:54 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-03-07 18:32:13 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
|
2015-04-21 17:12:54 +03:00
|
|
|
/*
|
|
|
|
|
* FIXME IPS should be fine as long as one plane is
|
|
|
|
|
* enabled, but in practice it seems to have problems
|
|
|
|
|
* when going from primary only to sprite only and vice
|
|
|
|
|
* versa.
|
|
|
|
|
*/
|
2014-03-07 18:32:13 +02:00
|
|
|
hsw_enable_ips(intel_crtc);
|
|
|
|
|
|
drm/i915: Track frontbuffer invalidation/flushing
So these are the guts of the new beast. This tracks when a frontbuffer
gets invalidated (due to frontbuffer rendering) and hence should be
constantly scaned out, and when it's flushed again and can be
compressed/one-shot-upload.
Rules for flushing are simple: The frontbuffer needs one more full
upload starting from the next vblank. Which means that the flushing
can _only_ be called once the frontbuffer update has been latched.
But this poses a problem for pageflips: We can't just delay the
flushing until the pageflip is latched, since that would pose the risk
that we override frontbuffer rendering that has been scheduled
in-between the pageflip ioctl and the actual latching.
To handle this track asynchronous invalidations (and also pageflip)
state per-ring and delay any in-between flushing until the rendering
has completed. And also cancel any delayed flushing if we get a new
invalidation request (whether delayed or not).
Also call intel_mark_fb_busy in both cases in all cases to make sure
that we keep the screen at the highest refresh rate both on flips,
synchronous plane updates and for frontbuffer rendering.
v2: Lots of improvements
Suggestions from Chris:
- Move invalidate/flush in flush_*_domain and set_to_*_domain.
- Drop the flush in busy_ioctl since it's redundant. Was a leftover
from an earlier concept to track flips/delayed flushes.
- Don't forget about the initial modeset enable/final disable.
Suggested by Chris.
Track flips accurately, too. Since flips complete independently of
rendering we need to track pending flips in a separate mask. Again if
an invalidate happens we need to cancel the evenutal flush to avoid
races.
v3:
Provide correct header declarations for flip functions. Currently not
needed outside of intel_display.c, but part of the proper interface.
v4: Add proper domain management to fbcon so that the fbcon buffer is
also tracked correctly.
v5: Fixup locking around the fbcon set_to_gtt_domain call.
v6: More comments from Chris:
- Split out fbcon changes.
- Drop superflous checks for potential scanout before calling intel_fb
functions - we can micro-optimize this later.
- s/intel_fb_/intel_fb_obj_/ to make it clear that this deals in gem
object. We already have precedence for fb_obj in the pin_and_fence
functions.
v7: Clarify the semantics of the flip flush handling by renaming
things a bit:
- Don't go through a gem object but take the relevant frontbuffer bits
directly. These functions center on the plane, the actual object is
irrelevant - even a flip to the same object as already active should
cause a flush.
- Add a new intel_frontbuffer_flip for synchronous plane updates. It
currently just calls intel_frontbuffer_flush since the implemenation
differs.
This way we achieve a clear split between one-shot update events on
one side and frontbuffer rendering with potentially a very long delay
between the invalidate and flush.
Chris and I also had some discussions about mark_busy and whether it
is appropriate to call from flush. But mark busy is a state which
should be derived from the 3 events (invalidate, flush, flip) we now
have by the users, like psr does by tracking relevant information in
psr.busy_frontbuffer_bits. DRRS (the only real use of mark_busy for
frontbuffer) needs to have similar logic. With that the overall
mark_busy in the core could be removed.
v8: Only when retiring gpu buffers only flush frontbuffer bits we
actually invalidated in a batch. Just for safety since before any
additional usage/invalidate we should always retire current rendering.
Suggested by Chris Wilson.
v9: Actually use intel_frontbuffer_flip in all appropriate places.
Spotted by Chris.
v10: Address more comments from Chris:
- Don't call _flip in set_base when the crtc is inactive, avoids redunancy
in the modeset case with the initial enabling of all planes.
- Add comments explaining that the initial/final plane enable/disable
still has work left to do before it's fully generic.
v11: Only invalidate for gtt/cpu access when writing. Spotted by Chris.
v12: s/_flush/_flip/ in intel_overlay.c per Chris' comment.
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-19 16:01:59 +02:00
|
|
|
/*
|
2015-04-21 17:12:54 +03:00
|
|
|
* Gen2 reports pipe underruns whenever all planes are disabled.
|
|
|
|
|
* So don't enable underrun reporting before at least some planes
|
|
|
|
|
* are enabled.
|
|
|
|
|
* FIXME: Need to fix the logic to work when we turn off all planes
|
|
|
|
|
* but leave the pipe running.
|
drm/i915: Track frontbuffer invalidation/flushing
So these are the guts of the new beast. This tracks when a frontbuffer
gets invalidated (due to frontbuffer rendering) and hence should be
constantly scaned out, and when it's flushed again and can be
compressed/one-shot-upload.
Rules for flushing are simple: The frontbuffer needs one more full
upload starting from the next vblank. Which means that the flushing
can _only_ be called once the frontbuffer update has been latched.
But this poses a problem for pageflips: We can't just delay the
flushing until the pageflip is latched, since that would pose the risk
that we override frontbuffer rendering that has been scheduled
in-between the pageflip ioctl and the actual latching.
To handle this track asynchronous invalidations (and also pageflip)
state per-ring and delay any in-between flushing until the rendering
has completed. And also cancel any delayed flushing if we get a new
invalidation request (whether delayed or not).
Also call intel_mark_fb_busy in both cases in all cases to make sure
that we keep the screen at the highest refresh rate both on flips,
synchronous plane updates and for frontbuffer rendering.
v2: Lots of improvements
Suggestions from Chris:
- Move invalidate/flush in flush_*_domain and set_to_*_domain.
- Drop the flush in busy_ioctl since it's redundant. Was a leftover
from an earlier concept to track flips/delayed flushes.
- Don't forget about the initial modeset enable/final disable.
Suggested by Chris.
Track flips accurately, too. Since flips complete independently of
rendering we need to track pending flips in a separate mask. Again if
an invalidate happens we need to cancel the evenutal flush to avoid
races.
v3:
Provide correct header declarations for flip functions. Currently not
needed outside of intel_display.c, but part of the proper interface.
v4: Add proper domain management to fbcon so that the fbcon buffer is
also tracked correctly.
v5: Fixup locking around the fbcon set_to_gtt_domain call.
v6: More comments from Chris:
- Split out fbcon changes.
- Drop superflous checks for potential scanout before calling intel_fb
functions - we can micro-optimize this later.
- s/intel_fb_/intel_fb_obj_/ to make it clear that this deals in gem
object. We already have precedence for fb_obj in the pin_and_fence
functions.
v7: Clarify the semantics of the flip flush handling by renaming
things a bit:
- Don't go through a gem object but take the relevant frontbuffer bits
directly. These functions center on the plane, the actual object is
irrelevant - even a flip to the same object as already active should
cause a flush.
- Add a new intel_frontbuffer_flip for synchronous plane updates. It
currently just calls intel_frontbuffer_flush since the implemenation
differs.
This way we achieve a clear split between one-shot update events on
one side and frontbuffer rendering with potentially a very long delay
between the invalidate and flush.
Chris and I also had some discussions about mark_busy and whether it
is appropriate to call from flush. But mark busy is a state which
should be derived from the 3 events (invalidate, flush, flip) we now
have by the users, like psr does by tracking relevant information in
psr.busy_frontbuffer_bits. DRRS (the only real use of mark_busy for
frontbuffer) needs to have similar logic. With that the overall
mark_busy in the core could be removed.
v8: Only when retiring gpu buffers only flush frontbuffer bits we
actually invalidated in a batch. Just for safety since before any
additional usage/invalidate we should always retire current rendering.
Suggested by Chris Wilson.
v9: Actually use intel_frontbuffer_flip in all appropriate places.
Spotted by Chris.
v10: Address more comments from Chris:
- Don't call _flip in set_base when the crtc is inactive, avoids redunancy
in the modeset case with the initial enabling of all planes.
- Add comments explaining that the initial/final plane enable/disable
still has work left to do before it's fully generic.
v11: Only invalidate for gtt/cpu access when writing. Spotted by Chris.
v12: s/_flush/_flip/ in intel_overlay.c per Chris' comment.
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-19 16:01:59 +02:00
|
|
|
*/
|
2015-04-21 17:12:54 +03:00
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
|
2015-10-30 19:22:21 +02:00
|
|
|
/* Underruns don't always raise interrupts, so check manually. */
|
|
|
|
|
intel_check_cpu_fifo_underruns(dev_priv);
|
|
|
|
|
intel_check_pch_fifo_underruns(dev_priv);
|
2014-03-07 18:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:12:54 +03:00
|
|
|
/**
|
|
|
|
|
* intel_pre_disable_primary - Perform operations before disabling primary plane
|
|
|
|
|
* @crtc: the CRTC whose primary plane is to be disabled
|
|
|
|
|
*
|
|
|
|
|
* Performs potentially sleeping operations that must be done before the
|
|
|
|
|
* primary plane is disabled, such as updating FBC and IPS. Note that this may
|
|
|
|
|
* be called due to an explicit primary plane update, or due to an implicit
|
|
|
|
|
* disable that is caused when a sprite plane completely hides the primary
|
|
|
|
|
* plane.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
intel_pre_disable_primary(struct drm_crtc *crtc)
|
2014-03-07 18:32:13 +02: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;
|
|
|
|
|
|
2015-04-21 17:12:54 +03:00
|
|
|
/*
|
|
|
|
|
* Gen2 reports pipe underruns whenever all planes are disabled.
|
|
|
|
|
* So diasble underrun reporting before all the planes get disabled.
|
|
|
|
|
* FIXME: Need to fix the logic to work when we turn off all planes
|
|
|
|
|
* but leave the pipe running.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
2014-03-07 18:32:13 +02:00
|
|
|
|
2015-04-21 17:12:54 +03:00
|
|
|
/*
|
|
|
|
|
* Vblank time updates from the shadow to live plane control register
|
|
|
|
|
* are blocked if the memory self-refresh mode is active at that
|
|
|
|
|
* moment. So to make sure the plane gets truly disabled, disable
|
|
|
|
|
* first the self-refresh mode. The self-refresh enable bit in turn
|
|
|
|
|
* will be checked/applied by the HW only at the next frame start
|
|
|
|
|
* event which is after the vblank start event, so we need to have a
|
|
|
|
|
* wait-for-vblank between disabling the plane and the pipe.
|
|
|
|
|
*/
|
2015-06-24 22:00:04 +03:00
|
|
|
if (HAS_GMCH_DISPLAY(dev)) {
|
2015-04-21 17:12:54 +03:00
|
|
|
intel_set_memory_cxsr(dev_priv, false);
|
2015-06-24 22:00:04 +03:00
|
|
|
dev_priv->wm.vlv.cxsr = false;
|
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
}
|
2015-04-21 17:12:54 +03:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME IPS should be fine as long as one plane is
|
|
|
|
|
* enabled, but in practice it seems to have problems
|
|
|
|
|
* when going from primary only to sprite only and vice
|
|
|
|
|
* versa.
|
|
|
|
|
*/
|
2014-03-07 18:32:13 +02:00
|
|
|
hsw_disable_ips(intel_crtc);
|
2015-04-21 17:12:54 +03:00
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:49 +02:00
|
|
|
static void intel_post_plane_update(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
|
2015-12-03 13:49:13 +01:00
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
2015-06-15 12:33:49 +02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
|
|
|
|
|
if (atomic->wait_vblank)
|
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
|
|
|
|
|
|
intel_frontbuffer_flip(dev, atomic->fb_bits);
|
|
|
|
|
|
2015-11-19 16:07:14 +01:00
|
|
|
crtc->wm.cxsr_allowed = true;
|
2015-06-24 22:00:07 +03:00
|
|
|
|
2015-11-19 16:07:16 +01:00
|
|
|
if (pipe_config->wm_changed && pipe_config->base.active)
|
2015-06-24 22:00:02 +03:00
|
|
|
intel_update_watermarks(&crtc->base);
|
|
|
|
|
|
2015-07-02 19:25:13 -03:00
|
|
|
if (atomic->update_fbc)
|
2015-10-13 19:13:25 -03:00
|
|
|
intel_fbc_update(crtc);
|
2015-06-15 12:33:49 +02:00
|
|
|
|
|
|
|
|
if (atomic->post_enable_primary)
|
|
|
|
|
intel_post_enable_primary(&crtc->base);
|
|
|
|
|
|
|
|
|
|
memset(atomic, 0, sizeof(*atomic));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_pre_plane_update(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2015-06-15 12:33:53 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-06-15 12:33:49 +02:00
|
|
|
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
|
2015-11-19 16:07:14 +01:00
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc->base.state);
|
2015-06-15 12:33:49 +02:00
|
|
|
|
2015-07-02 19:25:13 -03:00
|
|
|
if (atomic->disable_fbc)
|
2015-10-15 10:44:46 -03:00
|
|
|
intel_fbc_deactivate(crtc);
|
2015-06-15 12:33:49 +02:00
|
|
|
|
2015-06-26 13:55:54 -07:00
|
|
|
if (crtc->atomic.disable_ips)
|
|
|
|
|
hsw_disable_ips(crtc);
|
|
|
|
|
|
2015-06-15 12:33:49 +02:00
|
|
|
if (atomic->pre_disable_primary)
|
|
|
|
|
intel_pre_disable_primary(&crtc->base);
|
2015-06-24 22:00:07 +03:00
|
|
|
|
2015-11-19 16:07:14 +01:00
|
|
|
if (pipe_config->disable_cxsr) {
|
2015-06-24 22:00:07 +03:00
|
|
|
crtc->wm.cxsr_allowed = false;
|
|
|
|
|
intel_set_memory_cxsr(dev_priv, false);
|
|
|
|
|
}
|
2015-12-03 13:49:13 +01:00
|
|
|
|
2016-01-06 11:34:30 -08:00
|
|
|
/*
|
|
|
|
|
* IVB workaround: must disable low power watermarks for at least
|
|
|
|
|
* one frame before enabling scaling. LP watermarks can be re-enabled
|
|
|
|
|
* when scaling is disabled.
|
|
|
|
|
*
|
|
|
|
|
* WaCxSRDisabledForSpriteScaling:ivb
|
|
|
|
|
*/
|
|
|
|
|
if (pipe_config->disable_lp_wm) {
|
|
|
|
|
ilk_disable_lp_wm(dev);
|
|
|
|
|
intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're doing a modeset, we're done. No need to do any pre-vblank
|
|
|
|
|
* watermark programming here.
|
|
|
|
|
*/
|
|
|
|
|
if (needs_modeset(&pipe_config->base))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For platforms that support atomic watermarks, program the
|
|
|
|
|
* 'intermediate' watermarks immediately. On pre-gen9 platforms, these
|
|
|
|
|
* will be the intermediate values that are safe for both pre- and
|
|
|
|
|
* post- vblank; when vblank happens, the 'active' values will be set
|
|
|
|
|
* to the final 'target' values and we'll do this again to get the
|
|
|
|
|
* optimal watermarks. For gen9+ platforms, the values we program here
|
|
|
|
|
* will be the final target values which will get automatically latched
|
|
|
|
|
* at vblank time; no further programming will be necessary.
|
|
|
|
|
*
|
|
|
|
|
* If a platform hasn't been transitioned to atomic watermarks yet,
|
|
|
|
|
* we'll continue to update watermarks the old way, if flags tell
|
|
|
|
|
* us to.
|
|
|
|
|
*/
|
|
|
|
|
if (dev_priv->display.initial_watermarks != NULL)
|
|
|
|
|
dev_priv->display.initial_watermarks(pipe_config);
|
|
|
|
|
else if (pipe_config->wm_changed)
|
2015-12-03 13:49:13 +01:00
|
|
|
intel_update_watermarks(&crtc->base);
|
2015-06-15 12:33:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:51 +02:00
|
|
|
static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
|
2015-04-21 17:12:54 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-06-15 12:33:51 +02:00
|
|
|
struct drm_plane *p;
|
2015-04-21 17:12:54 +03:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
|
2015-04-21 17:12:55 +03:00
|
|
|
intel_crtc_dpms_overlay_disable(intel_crtc);
|
2015-04-21 17:12:52 +03:00
|
|
|
|
2015-06-15 12:33:51 +02:00
|
|
|
drm_for_each_plane_mask(p, dev, plane_mask)
|
|
|
|
|
to_intel_plane(p)->disable_plane(p, crtc);
|
2014-05-22 17:48:06 +03:00
|
|
|
|
drm/i915: Track frontbuffer invalidation/flushing
So these are the guts of the new beast. This tracks when a frontbuffer
gets invalidated (due to frontbuffer rendering) and hence should be
constantly scaned out, and when it's flushed again and can be
compressed/one-shot-upload.
Rules for flushing are simple: The frontbuffer needs one more full
upload starting from the next vblank. Which means that the flushing
can _only_ be called once the frontbuffer update has been latched.
But this poses a problem for pageflips: We can't just delay the
flushing until the pageflip is latched, since that would pose the risk
that we override frontbuffer rendering that has been scheduled
in-between the pageflip ioctl and the actual latching.
To handle this track asynchronous invalidations (and also pageflip)
state per-ring and delay any in-between flushing until the rendering
has completed. And also cancel any delayed flushing if we get a new
invalidation request (whether delayed or not).
Also call intel_mark_fb_busy in both cases in all cases to make sure
that we keep the screen at the highest refresh rate both on flips,
synchronous plane updates and for frontbuffer rendering.
v2: Lots of improvements
Suggestions from Chris:
- Move invalidate/flush in flush_*_domain and set_to_*_domain.
- Drop the flush in busy_ioctl since it's redundant. Was a leftover
from an earlier concept to track flips/delayed flushes.
- Don't forget about the initial modeset enable/final disable.
Suggested by Chris.
Track flips accurately, too. Since flips complete independently of
rendering we need to track pending flips in a separate mask. Again if
an invalidate happens we need to cancel the evenutal flush to avoid
races.
v3:
Provide correct header declarations for flip functions. Currently not
needed outside of intel_display.c, but part of the proper interface.
v4: Add proper domain management to fbcon so that the fbcon buffer is
also tracked correctly.
v5: Fixup locking around the fbcon set_to_gtt_domain call.
v6: More comments from Chris:
- Split out fbcon changes.
- Drop superflous checks for potential scanout before calling intel_fb
functions - we can micro-optimize this later.
- s/intel_fb_/intel_fb_obj_/ to make it clear that this deals in gem
object. We already have precedence for fb_obj in the pin_and_fence
functions.
v7: Clarify the semantics of the flip flush handling by renaming
things a bit:
- Don't go through a gem object but take the relevant frontbuffer bits
directly. These functions center on the plane, the actual object is
irrelevant - even a flip to the same object as already active should
cause a flush.
- Add a new intel_frontbuffer_flip for synchronous plane updates. It
currently just calls intel_frontbuffer_flush since the implemenation
differs.
This way we achieve a clear split between one-shot update events on
one side and frontbuffer rendering with potentially a very long delay
between the invalidate and flush.
Chris and I also had some discussions about mark_busy and whether it
is appropriate to call from flush. But mark busy is a state which
should be derived from the 3 events (invalidate, flush, flip) we now
have by the users, like psr does by tracking relevant information in
psr.busy_frontbuffer_bits. DRRS (the only real use of mark_busy for
frontbuffer) needs to have similar logic. With that the overall
mark_busy in the core could be removed.
v8: Only when retiring gpu buffers only flush frontbuffer bits we
actually invalidated in a batch. Just for safety since before any
additional usage/invalidate we should always retire current rendering.
Suggested by Chris Wilson.
v9: Actually use intel_frontbuffer_flip in all appropriate places.
Spotted by Chris.
v10: Address more comments from Chris:
- Don't call _flip in set_base when the crtc is inactive, avoids redunancy
in the modeset case with the initial enabling of all planes.
- Add comments explaining that the initial/final plane enable/disable
still has work left to do before it's fully generic.
v11: Only invalidate for gtt/cpu access when writing. Spotted by Chris.
v12: s/_flush/_flip/ in intel_overlay.c per Chris' comment.
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-19 16:01:59 +02:00
|
|
|
/*
|
|
|
|
|
* FIXME: Once we grow proper nuclear flip support out of this we need
|
|
|
|
|
* to compute the mask of flip planes precisely. For the time being
|
|
|
|
|
* consider this a flip to a NULL plane.
|
|
|
|
|
*/
|
|
|
|
|
intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
|
2014-03-07 18:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
2011-01-05 10: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-29 22:40:09 +02:00
|
|
|
struct intel_encoder *encoder;
|
2011-01-05 10:31:48 -08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
|
2015-06-01 12:49:52 +02:00
|
|
|
if (WARN_ON(intel_crtc->active))
|
2011-01-05 10:31:48 -08:00
|
|
|
return;
|
|
|
|
|
|
2015-10-30 19:21:31 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
2014-04-24 23:55:13 +02:00
|
|
|
intel_prepare_shared_dpll(intel_crtc);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_dp_encoder)
|
2015-02-13 15:32:59 +05:30
|
|
|
intel_dp_set_m_n(intel_crtc, M1_N1);
|
2014-04-24 23:55:08 +02:00
|
|
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
2014-04-24 23:55:08 +02:00
|
|
|
intel_cpu_transcoder_set_m_n(intel_crtc,
|
2015-01-15 14:55:25 +02:00
|
|
|
&intel_crtc->config->fdi_m_n, NULL);
|
2014-04-24 23:55:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ironlake_set_pipeconf(crtc);
|
|
|
|
|
|
2011-01-05 10:31:48 -08:00
|
|
|
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-12 17:57:57 -03:00
|
|
|
|
2014-09-30 10:56:47 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, 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-12 17:57:57 -03:00
|
|
|
|
2013-06-05 13:34:30 +02:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
2013-06-05 13:34:27 +02:00
|
|
|
if (encoder->pre_enable)
|
|
|
|
|
encoder->pre_enable(encoder);
|
2011-01-05 10:31:48 -08:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
2012-10-27 15:50:28 +02: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-12 19:27:14 +02:00
|
|
|
ironlake_fdi_pll_enable(intel_crtc);
|
2012-09-06 22:08:33 +02:00
|
|
|
} else {
|
|
|
|
|
assert_fdi_tx_disabled(dev_priv, pipe);
|
|
|
|
|
assert_fdi_rx_disabled(dev_priv, pipe);
|
|
|
|
|
}
|
2011-01-05 10:31:48 -08:00
|
|
|
|
2013-04-25 12:55:02 -07:00
|
|
|
ironlake_pfit_enable(intel_crtc);
|
2011-01-05 10:31:48 -08:00
|
|
|
|
2011-06-15 23:32:33 +02:00
|
|
|
/*
|
|
|
|
|
* On ILK+ LUT must be loaded before the pipe is running but with
|
|
|
|
|
* clocks enabled
|
|
|
|
|
*/
|
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
|
2013-09-10 11:39:55 +03:00
|
|
|
intel_update_watermarks(crtc);
|
2014-01-17 13:51:12 -02:00
|
|
|
intel_enable_pipe(intel_crtc);
|
2011-01-05 10:31:48 -08:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
2011-01-05 10:31:48 -08:00
|
|
|
ironlake_pch_enable(crtc);
|
2010-09-10 10:57:18 -07:00
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
2012-07-01 23:24:36 +02:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
encoder->enable(encoder);
|
2012-07-02 00:16:19 +02:00
|
|
|
|
|
|
|
|
if (HAS_PCH_CPT(dev))
|
2013-05-03 11:49:50 +02:00
|
|
|
cpt_verify_modeset(dev, intel_crtc->pipe);
|
2015-10-30 19:20:27 +02:00
|
|
|
|
|
|
|
|
/* Must wait for vblank to avoid spurious PCH FIFO underruns */
|
|
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_enable(intel_crtc);
|
2010-09-10 10:26:01 -07:00
|
|
|
}
|
|
|
|
|
|
2013-05-31 16:33:22 -03:00
|
|
|
/* IPS only exists on ULT machines and is tied to pipe A. */
|
|
|
|
|
static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
|
|
|
|
|
{
|
2013-06-24 18:29:34 +01:00
|
|
|
return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
|
2013-05-31 16:33:22 -03:00
|
|
|
}
|
|
|
|
|
|
2012-10-23 18:29:51 -02: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;
|
2015-06-01 12:50:09 +02:00
|
|
|
int pipe = intel_crtc->pipe, hsw_workaround_pipe;
|
|
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc->state);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-06-01 12:49:52 +02:00
|
|
|
if (WARN_ON(intel_crtc->active))
|
2012-10-23 18:29:51 -02:00
|
|
|
return;
|
|
|
|
|
|
2015-10-30 19:21:31 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
|
|
|
|
false);
|
|
|
|
|
|
2014-06-25 22:02:03 +03:00
|
|
|
if (intel_crtc_to_shared_dpll(intel_crtc))
|
|
|
|
|
intel_enable_shared_dpll(intel_crtc);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_dp_encoder)
|
2015-02-13 15:32:59 +05:30
|
|
|
intel_dp_set_m_n(intel_crtc, M1_N1);
|
2014-04-24 23:55:09 +02:00
|
|
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) {
|
|
|
|
|
I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder),
|
|
|
|
|
intel_crtc->config->pixel_multiplier - 1);
|
2014-09-30 10:30:22 -07:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
2014-04-24 23:55:09 +02:00
|
|
|
intel_cpu_transcoder_set_m_n(intel_crtc,
|
2015-01-15 14:55:25 +02:00
|
|
|
&intel_crtc->config->fdi_m_n, NULL);
|
2014-04-24 23:55:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
haswell_set_pipeconf(crtc);
|
|
|
|
|
|
|
|
|
|
intel_set_pipe_csc(crtc);
|
|
|
|
|
|
2012-10-23 18:29:51 -02:00
|
|
|
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-12 17:57:57 -03:00
|
|
|
|
2015-11-28 11:05:39 +01:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
|
|
else
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
|
2015-10-01 22:23:49 +05:30
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
2012-10-23 18:29:51 -02:00
|
|
|
if (encoder->pre_enable)
|
|
|
|
|
encoder->pre_enable(encoder);
|
2015-10-01 22:23:49 +05:30
|
|
|
}
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-10-29 21:25:53 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
2014-06-25 22:01:49 +03:00
|
|
|
dev_priv->display.fdi_link_train(crtc);
|
|
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder)
|
2015-10-01 22:23:49 +05:30
|
|
|
intel_ddi_enable_pipe_clock(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-09-02 15:19:26 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
2015-07-13 16:30:15 +02:00
|
|
|
skylake_pfit_enable(intel_crtc);
|
2015-01-21 17:19:54 -08:00
|
|
|
else
|
2015-09-02 15:19:26 -07:00
|
|
|
ironlake_pfit_enable(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* On ILK+ LUT must be loaded before the pipe is running but with
|
|
|
|
|
* clocks enabled
|
|
|
|
|
*/
|
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
|
2012-10-24 11:32:00 -02:00
|
|
|
intel_ddi_set_pipe_settings(crtc);
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder)
|
2015-10-01 22:23:49 +05:30
|
|
|
intel_ddi_enable_transcoder_func(crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2013-09-10 11:39:55 +03:00
|
|
|
intel_update_watermarks(crtc);
|
2014-01-17 13:51:12 -02:00
|
|
|
intel_enable_pipe(intel_crtc);
|
2013-05-31 16:33:22 -03:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
2012-10-31 18:12:22 -02:00
|
|
|
lpt_pch_enable(crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (intel_crtc->config->dp_encoder_is_mst)
|
2014-05-02 14:02:48 +10:00
|
|
|
intel_ddi_set_vc_payload_alloc(crtc, true);
|
|
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
2013-08-30 19:40:32 +03:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
2012-10-23 18:29:51 -02:00
|
|
|
encoder->enable(encoder);
|
2013-08-30 19:40:32 +03:00
|
|
|
intel_opregion_notify_encoder(encoder, true);
|
|
|
|
|
}
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-11-28 11:05:39 +01:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
2015-10-29 21:25:53 +02:00
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
|
|
|
|
true);
|
2015-11-28 11:05:39 +01:00
|
|
|
}
|
2015-10-29 21:25:53 +02:00
|
|
|
|
2013-09-20 16:21:19 -03:00
|
|
|
/* If we change the relative order between pipe/planes enabling, we need
|
|
|
|
|
* to change the workaround. */
|
2015-06-01 12:50:09 +02:00
|
|
|
hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
|
|
|
|
|
if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
|
|
|
|
|
intel_wait_for_vblank(dev, hsw_workaround_pipe);
|
|
|
|
|
intel_wait_for_vblank(dev, hsw_workaround_pipe);
|
|
|
|
|
}
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_enable(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
}
|
|
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force)
|
2013-05-08 10:36:30 +02:00
|
|
|
{
|
|
|
|
|
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. */
|
2015-08-27 15:44:05 +02:00
|
|
|
if (force || crtc->config->pch_pfit.enabled) {
|
2013-05-08 10:36:30 +02:00
|
|
|
I915_WRITE(PF_CTL(pipe), 0);
|
|
|
|
|
I915_WRITE(PF_WIN_POS(pipe), 0);
|
|
|
|
|
I915_WRITE(PF_WIN_SZ(pipe), 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-10 10:26:01 -07: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-29 22:40:09 +02:00
|
|
|
struct intel_encoder *encoder;
|
2010-09-10 10:26:01 -07:00
|
|
|
int pipe = intel_crtc->pipe;
|
2010-06-12 14:32:27 +08:00
|
|
|
|
2015-10-30 19:20:27 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
|
|
|
2012-07-10 10:42:52 +02:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
encoder->disable(encoder);
|
|
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
drm_crtc_vblank_off(crtc);
|
|
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
|
2015-11-20 22:09:18 +02:00
|
|
|
/*
|
|
|
|
|
* Sometimes spurious CPU pipe underruns happen when the
|
|
|
|
|
* pipe is already disabled, but FDI RX/TX is still enabled.
|
|
|
|
|
* Happens at least with VGA+HDMI cloning. Suppress them.
|
|
|
|
|
*/
|
|
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
|
|
|
|
|
2014-08-15 01:21:56 +03:00
|
|
|
intel_disable_pipe(intel_crtc);
|
2009-07-24 01:00:32 +08:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
ironlake_pfit_disable(intel_crtc, false);
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2015-11-20 22:09:18 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
2015-05-05 17:17:38 +03:00
|
|
|
ironlake_fdi_disable(crtc);
|
2015-11-20 22:09:18 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
|
|
|
|
}
|
2015-05-05 17:17:38 +03:00
|
|
|
|
2012-09-06 22:15:40 +02: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
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
2013-06-05 13:34:04 +02:00
|
|
|
ironlake_disable_pch_transcoder(dev_priv, pipe);
|
2010-09-10 10:26:01 -07:00
|
|
|
|
2013-06-05 13:34:04 +02:00
|
|
|
if (HAS_PCH_CPT(dev)) {
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg;
|
|
|
|
|
u32 temp;
|
|
|
|
|
|
2013-06-05 13:34:04 +02:00
|
|
|
/* disable TRANS_DP_CTL */
|
|
|
|
|
reg = TRANS_DP_CTL(pipe);
|
|
|
|
|
temp = I915_READ(reg);
|
|
|
|
|
temp &= ~(TRANS_DP_OUTPUT_ENABLE |
|
|
|
|
|
TRANS_DP_PORT_SEL_MASK);
|
|
|
|
|
temp |= TRANS_DP_PORT_SEL_NONE;
|
|
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
|
|
|
|
/* disable DPLL_SEL */
|
|
|
|
|
temp = I915_READ(PCH_DPLL_SEL);
|
2013-06-05 13:34:09 +02:00
|
|
|
temp &= ~(TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe));
|
2013-06-05 13:34:04 +02:00
|
|
|
I915_WRITE(PCH_DPLL_SEL, temp);
|
2011-02-07 12:26:52 -08:00
|
|
|
}
|
2010-04-08 09:43:27 +08:00
|
|
|
|
2013-06-05 13:34:04 +02:00
|
|
|
ironlake_fdi_pll_disable(intel_crtc);
|
|
|
|
|
}
|
2015-10-30 19:21:31 +02:00
|
|
|
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_disable_crtc(intel_crtc);
|
2010-09-10 10:26:01 -07:00
|
|
|
}
|
2009-11-25 13:09:38 +08:00
|
|
|
|
2012-10-23 18:29:51 -02:00
|
|
|
static void haswell_crtc_disable(struct drm_crtc *crtc)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2012-10-23 18:29:51 -02:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-04-20 17:11:53 +01:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
struct intel_encoder *encoder;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2015-10-29 21:25:53 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder)
|
|
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
|
|
|
|
false);
|
|
|
|
|
|
2013-08-30 19:40:32 +03:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
|
intel_opregion_notify_encoder(encoder, false);
|
2012-10-23 18:29:51 -02:00
|
|
|
encoder->disable(encoder);
|
2013-08-30 19:40:32 +03:00
|
|
|
}
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
drm_crtc_vblank_off(crtc);
|
|
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
|
2014-08-15 01:21:56 +03:00
|
|
|
intel_disable_pipe(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->dp_encoder_is_mst)
|
2014-08-18 21:27:34 +03:00
|
|
|
intel_ddi_set_vc_payload_alloc(crtc, false);
|
|
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder)
|
2015-10-01 22:23:49 +05:30
|
|
|
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-09-02 15:19:26 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
2015-07-13 16:30:15 +02:00
|
|
|
skylake_scaler_disable(intel_crtc);
|
2015-01-21 17:19:54 -08:00
|
|
|
else
|
2015-08-27 15:44:05 +02:00
|
|
|
ironlake_pfit_disable(intel_crtc, false);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder)
|
2015-10-01 22:23:49 +05:30
|
|
|
intel_ddi_disable_pipe_clock(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
|
2014-06-25 22:01:50 +03:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->post_disable)
|
|
|
|
|
encoder->post_disable(encoder);
|
2015-10-30 19:21:31 +02:00
|
|
|
|
2015-12-08 16:05:48 +02:00
|
|
|
if (intel_crtc->config->has_pch_encoder) {
|
|
|
|
|
lpt_disable_pch_transcoder(dev_priv);
|
2015-12-04 22:22:14 +02:00
|
|
|
lpt_disable_iclkip(dev_priv);
|
2015-12-08 16:05:48 +02:00
|
|
|
intel_ddi_fdi_disable(crtc);
|
|
|
|
|
|
2015-10-30 19:21:31 +02:00
|
|
|
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
|
|
|
|
true);
|
2015-12-08 16:05:48 +02:00
|
|
|
}
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_disable_crtc(intel_crtc);
|
2012-10-23 18:29:51 -02:00
|
|
|
}
|
|
|
|
|
|
2013-04-25 12:55:01 -07: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;
|
2015-01-15 14:55:25 +02:00
|
|
|
struct intel_crtc_state *pipe_config = crtc->config;
|
2013-04-25 12:55:01 -07:00
|
|
|
|
2015-01-15 14:55:24 +02:00
|
|
|
if (!pipe_config->gmch_pfit.control)
|
2013-04-25 12:55:01 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
2013-05-28 12:05:54 +02:00
|
|
|
* The panel fitter should only be adjusted whilst the pipe is disabled,
|
|
|
|
|
* according to register description and PRM.
|
2013-04-25 12:55:01 -07:00
|
|
|
*/
|
2013-05-28 12:05:54 +02:00
|
|
|
WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
|
|
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-04-25 12:55:01 -07:00
|
|
|
|
2013-04-25 12:55:02 -07:00
|
|
|
I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
|
|
|
|
|
I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
|
2013-04-25 22:52:18 +02: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-25 12:55:01 -07:00
|
|
|
}
|
|
|
|
|
|
2014-06-05 13:22:59 +10:00
|
|
|
static enum intel_display_power_domain port_to_power_domain(enum port port)
|
|
|
|
|
{
|
|
|
|
|
switch (port) {
|
|
|
|
|
case PORT_A:
|
2015-11-09 16:48:21 +01:00
|
|
|
return POWER_DOMAIN_PORT_DDI_A_LANES;
|
2014-06-05 13:22:59 +10:00
|
|
|
case PORT_B:
|
2015-11-09 16:48:21 +01:00
|
|
|
return POWER_DOMAIN_PORT_DDI_B_LANES;
|
2014-06-05 13:22:59 +10:00
|
|
|
case PORT_C:
|
2015-11-09 16:48:21 +01:00
|
|
|
return POWER_DOMAIN_PORT_DDI_C_LANES;
|
2014-06-05 13:22:59 +10:00
|
|
|
case PORT_D:
|
2015-11-09 16:48:21 +01:00
|
|
|
return POWER_DOMAIN_PORT_DDI_D_LANES;
|
2015-08-13 18:00:12 +08:00
|
|
|
case PORT_E:
|
2015-11-09 16:48:21 +01:00
|
|
|
return POWER_DOMAIN_PORT_DDI_E_LANES;
|
2014-06-05 13:22:59 +10:00
|
|
|
default:
|
2015-11-18 15:57:25 +02:00
|
|
|
MISSING_CASE(port);
|
2014-06-05 13:22:59 +10:00
|
|
|
return POWER_DOMAIN_PORT_OTHER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-16 15:01:04 +01:00
|
|
|
static enum intel_display_power_domain port_to_aux_power_domain(enum port port)
|
|
|
|
|
{
|
|
|
|
|
switch (port) {
|
|
|
|
|
case PORT_A:
|
|
|
|
|
return POWER_DOMAIN_AUX_A;
|
|
|
|
|
case PORT_B:
|
|
|
|
|
return POWER_DOMAIN_AUX_B;
|
|
|
|
|
case PORT_C:
|
|
|
|
|
return POWER_DOMAIN_AUX_C;
|
|
|
|
|
case PORT_D:
|
|
|
|
|
return POWER_DOMAIN_AUX_D;
|
|
|
|
|
case PORT_E:
|
|
|
|
|
/* FIXME: Check VBT for actual wiring of PORT E */
|
|
|
|
|
return POWER_DOMAIN_AUX_D;
|
|
|
|
|
default:
|
2015-11-18 15:57:25 +02:00
|
|
|
MISSING_CASE(port);
|
2015-11-16 15:01:04 +01:00
|
|
|
return POWER_DOMAIN_AUX_A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-04 19:22:57 +02:00
|
|
|
enum intel_display_power_domain
|
|
|
|
|
intel_display_port_power_domain(struct intel_encoder *intel_encoder)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_encoder->base.dev;
|
|
|
|
|
struct intel_digital_port *intel_dig_port;
|
|
|
|
|
|
|
|
|
|
switch (intel_encoder->type) {
|
|
|
|
|
case INTEL_OUTPUT_UNKNOWN:
|
|
|
|
|
/* Only DDI platforms should ever use this output type */
|
|
|
|
|
WARN_ON_ONCE(!HAS_DDI(dev));
|
|
|
|
|
case INTEL_OUTPUT_DISPLAYPORT:
|
|
|
|
|
case INTEL_OUTPUT_HDMI:
|
|
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
|
|
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
2014-06-05 13:22:59 +10:00
|
|
|
return port_to_power_domain(intel_dig_port->port);
|
2014-05-02 14:02:48 +10:00
|
|
|
case INTEL_OUTPUT_DP_MST:
|
|
|
|
|
intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
|
|
|
|
|
return port_to_power_domain(intel_dig_port->port);
|
2014-03-04 19:22:57 +02:00
|
|
|
case INTEL_OUTPUT_ANALOG:
|
|
|
|
|
return POWER_DOMAIN_PORT_CRT;
|
|
|
|
|
case INTEL_OUTPUT_DSI:
|
|
|
|
|
return POWER_DOMAIN_PORT_DSI;
|
|
|
|
|
default:
|
|
|
|
|
return POWER_DOMAIN_PORT_OTHER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-16 15:01:04 +01:00
|
|
|
enum intel_display_power_domain
|
|
|
|
|
intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_encoder->base.dev;
|
|
|
|
|
struct intel_digital_port *intel_dig_port;
|
|
|
|
|
|
|
|
|
|
switch (intel_encoder->type) {
|
|
|
|
|
case INTEL_OUTPUT_UNKNOWN:
|
2015-11-18 15:57:24 +02:00
|
|
|
case INTEL_OUTPUT_HDMI:
|
|
|
|
|
/*
|
|
|
|
|
* Only DDI platforms should ever use these output types.
|
|
|
|
|
* We can get here after the HDMI detect code has already set
|
|
|
|
|
* the type of the shared encoder. Since we can't be sure
|
|
|
|
|
* what's the status of the given connectors, play safe and
|
|
|
|
|
* run the DP detection too.
|
|
|
|
|
*/
|
2015-11-16 15:01:04 +01:00
|
|
|
WARN_ON_ONCE(!HAS_DDI(dev));
|
|
|
|
|
case INTEL_OUTPUT_DISPLAYPORT:
|
|
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
|
|
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
|
|
|
|
return port_to_aux_power_domain(intel_dig_port->port);
|
|
|
|
|
case INTEL_OUTPUT_DP_MST:
|
|
|
|
|
intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
|
|
|
|
|
return port_to_aux_power_domain(intel_dig_port->port);
|
|
|
|
|
default:
|
2015-11-18 15:57:25 +02:00
|
|
|
MISSING_CASE(intel_encoder->type);
|
2015-11-16 15:01:04 +01:00
|
|
|
return POWER_DOMAIN_AUX_A;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-04 19:22:57 +02:00
|
|
|
static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
|
2014-03-05 16:20:52 +02:00
|
|
|
{
|
2014-03-04 19:22:57 +02:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct intel_encoder *intel_encoder;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
2014-03-05 16:20:52 +02:00
|
|
|
unsigned long mask;
|
2015-10-29 21:25:50 +02:00
|
|
|
enum transcoder transcoder = intel_crtc->config->cpu_transcoder;
|
2014-03-05 16:20:52 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
if (!crtc->state->active)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2014-03-05 16:20:52 +02:00
|
|
|
mask = BIT(POWER_DOMAIN_PIPE(pipe));
|
|
|
|
|
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->pch_pfit.enabled ||
|
|
|
|
|
intel_crtc->config->pch_pfit.force_thru)
|
2014-03-05 16:20:52 +02:00
|
|
|
mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
|
|
|
|
|
|
2014-03-04 19:22:57 +02:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
|
|
|
|
|
mask |= BIT(intel_display_port_power_domain(intel_encoder));
|
|
|
|
|
|
2014-03-05 16:20:52 +02:00
|
|
|
return mask;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
static unsigned long modeset_get_crtc_power_domains(struct drm_crtc *crtc)
|
2014-03-05 16:20:52 +02:00
|
|
|
{
|
2015-07-13 16:30:27 +02:00
|
|
|
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
enum intel_display_power_domain domain;
|
|
|
|
|
unsigned long domains, new_domains, old_domains;
|
2014-03-05 16:20:52 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
old_domains = intel_crtc->enabled_power_domains;
|
|
|
|
|
intel_crtc->enabled_power_domains = new_domains = get_crtc_power_domains(crtc);
|
2014-03-05 16:20:52 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
domains = new_domains & ~old_domains;
|
|
|
|
|
|
|
|
|
|
for_each_power_domain(domain, domains)
|
|
|
|
|
intel_display_power_get(dev_priv, domain);
|
|
|
|
|
|
|
|
|
|
return old_domains & ~new_domains;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
|
|
|
|
|
unsigned long domains)
|
|
|
|
|
{
|
|
|
|
|
enum intel_display_power_domain domain;
|
|
|
|
|
|
|
|
|
|
for_each_power_domain(domain, domains)
|
|
|
|
|
intel_display_power_put(dev_priv, domain);
|
|
|
|
|
}
|
2014-03-05 16:20:52 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
|
|
|
|
|
{
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
2015-07-13 16:30:27 +02:00
|
|
|
struct drm_device *dev = state->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
unsigned long put_domains[I915_MAX_PIPES] = {};
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
int i;
|
2014-03-05 16:20:52 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
if (needs_modeset(crtc->state))
|
|
|
|
|
put_domains[to_intel_crtc(crtc)->pipe] =
|
|
|
|
|
modeset_get_crtc_power_domains(crtc);
|
2014-03-05 16:20:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
if (dev_priv->display.modeset_commit_cdclk &&
|
|
|
|
|
intel_state->dev_cdclk != dev_priv->cdclk_freq)
|
|
|
|
|
dev_priv->display.modeset_commit_cdclk(state);
|
2014-11-06 14:49:12 +02:00
|
|
|
|
2015-07-13 16:30:27 +02:00
|
|
|
for (i = 0; i < I915_MAX_PIPES; i++)
|
|
|
|
|
if (put_domains[i])
|
|
|
|
|
modeset_put_power_domains(dev_priv, put_domains[i]);
|
2014-03-05 16:20:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-18 14:36:59 +03:00
|
|
|
static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
int max_cdclk_freq = dev_priv->max_cdclk_freq;
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev_priv)->gen >= 9 ||
|
|
|
|
|
IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
|
|
|
|
return max_cdclk_freq;
|
|
|
|
|
else if (IS_CHERRYVIEW(dev_priv))
|
|
|
|
|
return max_cdclk_freq*95/100;
|
|
|
|
|
else if (INTEL_INFO(dev_priv)->gen < 4)
|
|
|
|
|
return 2*max_cdclk_freq*90/100;
|
|
|
|
|
else
|
|
|
|
|
return max_cdclk_freq*90/100;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-04 18:21:33 +01:00
|
|
|
static void intel_update_max_cdclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2015-10-28 04:16:45 -07:00
|
|
|
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
|
2015-06-04 18:21:33 +01:00
|
|
|
u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
|
|
|
|
|
|
|
|
|
|
if (limit == SKL_DFSM_CDCLK_LIMIT_675)
|
|
|
|
|
dev_priv->max_cdclk_freq = 675000;
|
|
|
|
|
else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
|
|
|
|
|
dev_priv->max_cdclk_freq = 540000;
|
|
|
|
|
else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
|
|
|
|
|
dev_priv->max_cdclk_freq = 450000;
|
|
|
|
|
else
|
|
|
|
|
dev_priv->max_cdclk_freq = 337500;
|
|
|
|
|
} else if (IS_BROADWELL(dev)) {
|
|
|
|
|
/*
|
|
|
|
|
* FIXME with extra cooling we can allow
|
|
|
|
|
* 540 MHz for ULX and 675 Mhz for ULT.
|
|
|
|
|
* How can we know if extra cooling is
|
|
|
|
|
* available? PCI ID, VTB, something else?
|
|
|
|
|
*/
|
|
|
|
|
if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
|
|
dev_priv->max_cdclk_freq = 450000;
|
|
|
|
|
else if (IS_BDW_ULX(dev))
|
|
|
|
|
dev_priv->max_cdclk_freq = 450000;
|
|
|
|
|
else if (IS_BDW_ULT(dev))
|
|
|
|
|
dev_priv->max_cdclk_freq = 540000;
|
|
|
|
|
else
|
|
|
|
|
dev_priv->max_cdclk_freq = 675000;
|
2015-06-12 10:11:32 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev)) {
|
|
|
|
|
dev_priv->max_cdclk_freq = 320000;
|
2015-06-04 18:21:33 +01:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
|
|
|
|
dev_priv->max_cdclk_freq = 400000;
|
|
|
|
|
} else {
|
|
|
|
|
/* otherwise assume cdclk is fixed */
|
|
|
|
|
dev_priv->max_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-18 14:36:59 +03:00
|
|
|
dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
|
|
|
|
|
|
2015-06-04 18:21:33 +01:00
|
|
|
DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
|
|
|
|
|
dev_priv->max_cdclk_freq);
|
2015-08-18 14:36:59 +03:00
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
|
|
|
|
|
dev_priv->max_dotclk_freq);
|
2015-06-04 18:21:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_update_cdclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
|
|
|
|
|
DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
|
|
|
|
|
dev_priv->cdclk_freq);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Program the gmbus_freq based on the cdclk frequency.
|
|
|
|
|
* BSpec erroneously claims we should aim for 4MHz, but
|
|
|
|
|
* in fact 1MHz is the correct frequency.
|
|
|
|
|
*/
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2015-06-04 18:21:33 +01:00
|
|
|
/*
|
|
|
|
|
* Program the gmbus_freq based on the cdclk frequency.
|
|
|
|
|
* BSpec erroneously claims we should aim for 4MHz, but
|
|
|
|
|
* in fact 1MHz is the correct frequency.
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dev_priv->max_cdclk_freq == 0)
|
|
|
|
|
intel_update_max_cdclk(dev);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-04 18:21:29 +01:00
|
|
|
static void broxton_set_cdclk(struct drm_device *dev, int frequency)
|
2014-11-24 13:37:39 +05:30
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t divider;
|
|
|
|
|
uint32_t ratio;
|
|
|
|
|
uint32_t current_freq;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* frequency = 19.2MHz * ratio / 2 / div{1,1.5,2,4} */
|
|
|
|
|
switch (frequency) {
|
|
|
|
|
case 144000:
|
|
|
|
|
divider = BXT_CDCLK_CD2X_DIV_SEL_4;
|
|
|
|
|
ratio = BXT_DE_PLL_RATIO(60);
|
|
|
|
|
break;
|
|
|
|
|
case 288000:
|
|
|
|
|
divider = BXT_CDCLK_CD2X_DIV_SEL_2;
|
|
|
|
|
ratio = BXT_DE_PLL_RATIO(60);
|
|
|
|
|
break;
|
|
|
|
|
case 384000:
|
|
|
|
|
divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
|
|
|
|
|
ratio = BXT_DE_PLL_RATIO(60);
|
|
|
|
|
break;
|
|
|
|
|
case 576000:
|
|
|
|
|
divider = BXT_CDCLK_CD2X_DIV_SEL_1;
|
|
|
|
|
ratio = BXT_DE_PLL_RATIO(60);
|
|
|
|
|
break;
|
|
|
|
|
case 624000:
|
|
|
|
|
divider = BXT_CDCLK_CD2X_DIV_SEL_1;
|
|
|
|
|
ratio = BXT_DE_PLL_RATIO(65);
|
|
|
|
|
break;
|
|
|
|
|
case 19200:
|
|
|
|
|
/*
|
|
|
|
|
* Bypass frequency with DE PLL disabled. Init ratio, divider
|
|
|
|
|
* to suppress GCC warning.
|
|
|
|
|
*/
|
|
|
|
|
ratio = 0;
|
|
|
|
|
divider = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
DRM_ERROR("unsupported CDCLK freq %d", frequency);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
/* Inform power controller of upcoming frequency change */
|
|
|
|
|
ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
|
|
|
|
|
0x80000000);
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
|
DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
|
|
|
|
|
ret, frequency);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_freq = I915_READ(CDCLK_CTL) & CDCLK_FREQ_DECIMAL_MASK;
|
|
|
|
|
/* convert from .1 fixpoint MHz with -1MHz offset to kHz */
|
|
|
|
|
current_freq = current_freq * 500 + 1000;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* DE PLL has to be disabled when
|
|
|
|
|
* - setting to 19.2MHz (bypass, PLL isn't used)
|
|
|
|
|
* - before setting to 624MHz (PLL needs toggling)
|
|
|
|
|
* - before setting to any frequency from 624MHz (PLL needs toggling)
|
|
|
|
|
*/
|
|
|
|
|
if (frequency == 19200 || frequency == 624000 ||
|
|
|
|
|
current_freq == 624000) {
|
|
|
|
|
I915_WRITE(BXT_DE_PLL_ENABLE, ~BXT_DE_PLL_PLL_ENABLE);
|
|
|
|
|
/* Timeout 200us */
|
|
|
|
|
if (wait_for(!(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK),
|
|
|
|
|
1))
|
|
|
|
|
DRM_ERROR("timout waiting for DE PLL unlock\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frequency != 19200) {
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
val = I915_READ(BXT_DE_PLL_CTL);
|
|
|
|
|
val &= ~BXT_DE_PLL_RATIO_MASK;
|
|
|
|
|
val |= ratio;
|
|
|
|
|
I915_WRITE(BXT_DE_PLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
|
|
|
|
|
/* Timeout 200us */
|
|
|
|
|
if (wait_for(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK, 1))
|
|
|
|
|
DRM_ERROR("timeout waiting for DE PLL lock\n");
|
|
|
|
|
|
|
|
|
|
val = I915_READ(CDCLK_CTL);
|
|
|
|
|
val &= ~BXT_CDCLK_CD2X_DIV_SEL_MASK;
|
|
|
|
|
val |= divider;
|
|
|
|
|
/*
|
|
|
|
|
* Disable SSA Precharge when CD clock frequency < 500 MHz,
|
|
|
|
|
* enable otherwise.
|
|
|
|
|
*/
|
|
|
|
|
val &= ~BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
|
|
|
|
if (frequency >= 500000)
|
|
|
|
|
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
|
|
|
|
|
|
|
|
|
val &= ~CDCLK_FREQ_DECIMAL_MASK;
|
|
|
|
|
/* convert from kHz to .1 fixpoint MHz with -1MHz offset */
|
|
|
|
|
val |= (frequency - 1000) / 500;
|
|
|
|
|
I915_WRITE(CDCLK_CTL, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
|
|
|
|
|
DIV_ROUND_UP(frequency, 25000));
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
|
DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
|
|
|
|
|
ret, frequency);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-04 18:21:34 +01:00
|
|
|
intel_update_cdclk(dev);
|
2014-11-24 13:37:39 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void broxton_init_cdclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
|
|
|
|
|
* or else the reset will hang because there is no PCH to respond.
|
|
|
|
|
* Move the handshake programming to initialization sequence.
|
|
|
|
|
* Previously was left up to BIOS.
|
|
|
|
|
*/
|
|
|
|
|
val = I915_READ(HSW_NDE_RSTWRN_OPT);
|
|
|
|
|
val &= ~RESET_PCH_HANDSHAKE_ENABLE;
|
|
|
|
|
I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
|
|
|
|
|
|
|
|
|
|
/* Enable PG1 for cdclk */
|
|
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
|
|
|
|
|
|
|
/* check if cd clock is enabled */
|
|
|
|
|
if (I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_PLL_ENABLE) {
|
|
|
|
|
DRM_DEBUG_KMS("Display already initialized\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME:
|
|
|
|
|
* - The initial CDCLK needs to be read from VBT.
|
|
|
|
|
* Need to make this change after VBT has changes for BXT.
|
|
|
|
|
* - check if setting the max (or any) cdclk freq is really necessary
|
|
|
|
|
* here, it belongs to modeset time
|
|
|
|
|
*/
|
|
|
|
|
broxton_set_cdclk(dev, 624000);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
|
2015-05-06 14:28:57 +03:00
|
|
|
POSTING_READ(DBUF_CTL);
|
|
|
|
|
|
2014-11-24 13:37:39 +05:30
|
|
|
udelay(10);
|
|
|
|
|
|
|
|
|
|
if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
|
|
|
|
|
DRM_ERROR("DBuf power enable timeout!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void broxton_uninit_cdclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
|
2015-05-06 14:28:57 +03:00
|
|
|
POSTING_READ(DBUF_CTL);
|
|
|
|
|
|
2014-11-24 13:37:39 +05:30
|
|
|
udelay(10);
|
|
|
|
|
|
|
|
|
|
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
|
|
|
|
|
DRM_ERROR("DBuf power disable timeout!\n");
|
|
|
|
|
|
|
|
|
|
/* Set minimum (bypass) frequency, in effect turning off the DE PLL */
|
|
|
|
|
broxton_set_cdclk(dev, 19200);
|
|
|
|
|
|
|
|
|
|
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
|
|
|
|
|
}
|
|
|
|
|
|
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This
includes:
- Hooking the PCH to the reset logic
- Restoring CDCDLK
- Enabling the DDB power
Among those, only the CDCDLK one is a bit tricky. There's some
complexity in that:
- DPLL0 (which is the source for CDCLK) has two VCOs, each with a set
of supported frequencies. As eDP also uses DPLL0 for its link rate,
once DPLL0 is on, we restrict the possible eDP link rates the chosen
VCO.
- CDCLK also limits the bandwidth available to push pixels.
So, as a first step, this commit restore what the BIOS set, until I can
do more testing.
In case that's of interest for the reviewer, I've unit tested the
function that derives the decimal frequency field:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
static const struct dpll_freq {
unsigned int freq;
unsigned int decimal;
} freqs[] = {
{ .freq = 308570, .decimal = 0b01001100111},
{ .freq = 337500, .decimal = 0b01010100001},
{ .freq = 432000, .decimal = 0b01101011110},
{ .freq = 450000, .decimal = 0b01110000010},
{ .freq = 540000, .decimal = 0b10000110110},
{ .freq = 617140, .decimal = 0b10011010000},
{ .freq = 675000, .decimal = 0b10101000100},
};
static void intbits(unsigned int v)
{
int i;
for(i = 10; i >= 0; i--)
putchar('0' + ((v >> i) & 1));
}
static unsigned int freq_decimal(unsigned int freq /* in kHz */)
{
return (freq - 1000) / 500;
}
static void test_freq(const struct dpll_freq *entry)
{
unsigned int decimal = freq_decimal(entry->freq);
printf("freq: %d, expected: ", entry->freq);
intbits(entry->decimal);
printf(", got: ");
intbits(decimal);
putchar('\n');
assert(decimal == entry->decimal);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < ARRAY_SIZE(freqs); i++)
test_freq(&freqs[i]);
return 0;
}
v2:
- Rebase on top of -nightly
- Use (freq - 1000) / 500 for the decimal frequency (Ville)
- Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville)
- Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to
be consistent with the BXT code (Ville)
- Store boot CDCLK in ddi_pll_init (Ville)
- Merge dev_priv's skl_boot_cdclk into cdclk_freq
- Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville)
- Replace various '0' by SKL_DPLL0 to be a bit more explicit that
we're programming DPLL0
- Busy poll the PCU before doing the frequency change. It takes about
3/4 cycles, each separated by 10us, to get the ACK from the CPU
(Ville)
v3:
- Restore dev_priv->skl_boot_cdclk, leaving unification with
dev_priv->cdclk_freq for a later patch (Daniel, Ville)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-05-21 16:37:48 +01:00
|
|
|
static const struct skl_cdclk_entry {
|
|
|
|
|
unsigned int freq;
|
|
|
|
|
unsigned int vco;
|
|
|
|
|
} skl_cdclk_frequencies[] = {
|
|
|
|
|
{ .freq = 308570, .vco = 8640 },
|
|
|
|
|
{ .freq = 337500, .vco = 8100 },
|
|
|
|
|
{ .freq = 432000, .vco = 8640 },
|
|
|
|
|
{ .freq = 450000, .vco = 8100 },
|
|
|
|
|
{ .freq = 540000, .vco = 8100 },
|
|
|
|
|
{ .freq = 617140, .vco = 8640 },
|
|
|
|
|
{ .freq = 675000, .vco = 8100 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static unsigned int skl_cdclk_decimal(unsigned int freq)
|
|
|
|
|
{
|
|
|
|
|
return (freq - 1000) / 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned int skl_cdclk_get_vco(unsigned int freq)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(skl_cdclk_frequencies); i++) {
|
|
|
|
|
const struct skl_cdclk_entry *e = &skl_cdclk_frequencies[i];
|
|
|
|
|
|
|
|
|
|
if (e->freq == freq)
|
|
|
|
|
return e->vco;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 8100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
skl_dpll0_enable(struct drm_i915_private *dev_priv, unsigned int required_vco)
|
|
|
|
|
{
|
|
|
|
|
unsigned int min_freq;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
/* select the minimum CDCLK before enabling DPLL 0 */
|
|
|
|
|
val = I915_READ(CDCLK_CTL);
|
|
|
|
|
val &= ~CDCLK_FREQ_SEL_MASK | ~CDCLK_FREQ_DECIMAL_MASK;
|
|
|
|
|
val |= CDCLK_FREQ_337_308;
|
|
|
|
|
|
|
|
|
|
if (required_vco == 8640)
|
|
|
|
|
min_freq = 308570;
|
|
|
|
|
else
|
|
|
|
|
min_freq = 337500;
|
|
|
|
|
|
|
|
|
|
val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_freq);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(CDCLK_CTL, val);
|
|
|
|
|
POSTING_READ(CDCLK_CTL);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We always enable DPLL0 with the lowest link rate possible, but still
|
|
|
|
|
* taking into account the VCO required to operate the eDP panel at the
|
|
|
|
|
* desired frequency. The usual DP link rates operate with a VCO of
|
|
|
|
|
* 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
|
|
|
|
|
* The modeset code is responsible for the selection of the exact link
|
|
|
|
|
* rate later on, with the constraint of choosing a frequency that
|
|
|
|
|
* works with required_vco.
|
|
|
|
|
*/
|
|
|
|
|
val = I915_READ(DPLL_CTRL1);
|
|
|
|
|
|
|
|
|
|
val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
|
|
|
|
|
DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
|
|
|
|
|
val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
|
|
|
|
|
if (required_vco == 8640)
|
|
|
|
|
val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
|
|
|
|
|
SKL_DPLL0);
|
|
|
|
|
else
|
|
|
|
|
val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
|
|
|
|
|
SKL_DPLL0);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(DPLL_CTRL1, val);
|
|
|
|
|
POSTING_READ(DPLL_CTRL1);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
|
|
|
|
|
|
|
|
|
|
if (wait_for(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK, 5))
|
|
|
|
|
DRM_ERROR("DPLL0 not locked\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool skl_cdclk_pcu_ready(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
/* inform PCU we want to change CDCLK */
|
|
|
|
|
val = SKL_CDCLK_PREPARE_FOR_CHANGE;
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
ret = sandybridge_pcode_read(dev_priv, SKL_PCODE_CDCLK_CONTROL, &val);
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
return ret == 0 && (val & SKL_CDCLK_READY_FOR_CHANGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
|
|
|
if (skl_cdclk_pcu_ready(dev_priv))
|
|
|
|
|
return true;
|
|
|
|
|
udelay(10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void skl_set_cdclk(struct drm_i915_private *dev_priv, unsigned int freq)
|
|
|
|
|
{
|
2015-06-04 18:21:33 +01:00
|
|
|
struct drm_device *dev = dev_priv->dev;
|
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This
includes:
- Hooking the PCH to the reset logic
- Restoring CDCDLK
- Enabling the DDB power
Among those, only the CDCDLK one is a bit tricky. There's some
complexity in that:
- DPLL0 (which is the source for CDCLK) has two VCOs, each with a set
of supported frequencies. As eDP also uses DPLL0 for its link rate,
once DPLL0 is on, we restrict the possible eDP link rates the chosen
VCO.
- CDCLK also limits the bandwidth available to push pixels.
So, as a first step, this commit restore what the BIOS set, until I can
do more testing.
In case that's of interest for the reviewer, I've unit tested the
function that derives the decimal frequency field:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
static const struct dpll_freq {
unsigned int freq;
unsigned int decimal;
} freqs[] = {
{ .freq = 308570, .decimal = 0b01001100111},
{ .freq = 337500, .decimal = 0b01010100001},
{ .freq = 432000, .decimal = 0b01101011110},
{ .freq = 450000, .decimal = 0b01110000010},
{ .freq = 540000, .decimal = 0b10000110110},
{ .freq = 617140, .decimal = 0b10011010000},
{ .freq = 675000, .decimal = 0b10101000100},
};
static void intbits(unsigned int v)
{
int i;
for(i = 10; i >= 0; i--)
putchar('0' + ((v >> i) & 1));
}
static unsigned int freq_decimal(unsigned int freq /* in kHz */)
{
return (freq - 1000) / 500;
}
static void test_freq(const struct dpll_freq *entry)
{
unsigned int decimal = freq_decimal(entry->freq);
printf("freq: %d, expected: ", entry->freq);
intbits(entry->decimal);
printf(", got: ");
intbits(decimal);
putchar('\n');
assert(decimal == entry->decimal);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < ARRAY_SIZE(freqs); i++)
test_freq(&freqs[i]);
return 0;
}
v2:
- Rebase on top of -nightly
- Use (freq - 1000) / 500 for the decimal frequency (Ville)
- Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville)
- Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to
be consistent with the BXT code (Ville)
- Store boot CDCLK in ddi_pll_init (Ville)
- Merge dev_priv's skl_boot_cdclk into cdclk_freq
- Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville)
- Replace various '0' by SKL_DPLL0 to be a bit more explicit that
we're programming DPLL0
- Busy poll the PCU before doing the frequency change. It takes about
3/4 cycles, each separated by 10us, to get the ACK from the CPU
(Ville)
v3:
- Restore dev_priv->skl_boot_cdclk, leaving unification with
dev_priv->cdclk_freq for a later patch (Daniel, Ville)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-05-21 16:37:48 +01:00
|
|
|
u32 freq_select, pcu_ack;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_DRIVER("Changing CDCLK to %dKHz\n", freq);
|
|
|
|
|
|
|
|
|
|
if (!skl_cdclk_wait_for_pcu_ready(dev_priv)) {
|
|
|
|
|
DRM_ERROR("failed to inform PCU about cdclk change\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set CDCLK_CTL */
|
|
|
|
|
switch(freq) {
|
|
|
|
|
case 450000:
|
|
|
|
|
case 432000:
|
|
|
|
|
freq_select = CDCLK_FREQ_450_432;
|
|
|
|
|
pcu_ack = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 540000:
|
|
|
|
|
freq_select = CDCLK_FREQ_540;
|
|
|
|
|
pcu_ack = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 308570:
|
|
|
|
|
case 337500:
|
|
|
|
|
default:
|
|
|
|
|
freq_select = CDCLK_FREQ_337_308;
|
|
|
|
|
pcu_ack = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 617140:
|
|
|
|
|
case 675000:
|
|
|
|
|
freq_select = CDCLK_FREQ_675_617;
|
|
|
|
|
pcu_ack = 3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(freq));
|
|
|
|
|
POSTING_READ(CDCLK_CTL);
|
|
|
|
|
|
|
|
|
|
/* inform PCU of the change */
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
2015-06-04 18:21:33 +01:00
|
|
|
|
|
|
|
|
intel_update_cdclk(dev);
|
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This
includes:
- Hooking the PCH to the reset logic
- Restoring CDCDLK
- Enabling the DDB power
Among those, only the CDCDLK one is a bit tricky. There's some
complexity in that:
- DPLL0 (which is the source for CDCLK) has two VCOs, each with a set
of supported frequencies. As eDP also uses DPLL0 for its link rate,
once DPLL0 is on, we restrict the possible eDP link rates the chosen
VCO.
- CDCLK also limits the bandwidth available to push pixels.
So, as a first step, this commit restore what the BIOS set, until I can
do more testing.
In case that's of interest for the reviewer, I've unit tested the
function that derives the decimal frequency field:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
static const struct dpll_freq {
unsigned int freq;
unsigned int decimal;
} freqs[] = {
{ .freq = 308570, .decimal = 0b01001100111},
{ .freq = 337500, .decimal = 0b01010100001},
{ .freq = 432000, .decimal = 0b01101011110},
{ .freq = 450000, .decimal = 0b01110000010},
{ .freq = 540000, .decimal = 0b10000110110},
{ .freq = 617140, .decimal = 0b10011010000},
{ .freq = 675000, .decimal = 0b10101000100},
};
static void intbits(unsigned int v)
{
int i;
for(i = 10; i >= 0; i--)
putchar('0' + ((v >> i) & 1));
}
static unsigned int freq_decimal(unsigned int freq /* in kHz */)
{
return (freq - 1000) / 500;
}
static void test_freq(const struct dpll_freq *entry)
{
unsigned int decimal = freq_decimal(entry->freq);
printf("freq: %d, expected: ", entry->freq);
intbits(entry->decimal);
printf(", got: ");
intbits(decimal);
putchar('\n');
assert(decimal == entry->decimal);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < ARRAY_SIZE(freqs); i++)
test_freq(&freqs[i]);
return 0;
}
v2:
- Rebase on top of -nightly
- Use (freq - 1000) / 500 for the decimal frequency (Ville)
- Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville)
- Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to
be consistent with the BXT code (Ville)
- Store boot CDCLK in ddi_pll_init (Ville)
- Merge dev_priv's skl_boot_cdclk into cdclk_freq
- Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville)
- Replace various '0' by SKL_DPLL0 to be a bit more explicit that
we're programming DPLL0
- Busy poll the PCU before doing the frequency change. It takes about
3/4 cycles, each separated by 10us, to get the ACK from the CPU
(Ville)
v3:
- Restore dev_priv->skl_boot_cdclk, leaving unification with
dev_priv->cdclk_freq for a later patch (Daniel, Ville)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-05-21 16:37:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
/* disable DBUF power */
|
|
|
|
|
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
|
|
|
|
|
POSTING_READ(DBUF_CTL);
|
|
|
|
|
|
|
|
|
|
udelay(10);
|
|
|
|
|
|
|
|
|
|
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
|
|
|
|
|
DRM_ERROR("DBuf power disable timeout\n");
|
|
|
|
|
|
2015-11-04 19:24:18 +02:00
|
|
|
/* disable DPLL0 */
|
|
|
|
|
I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
|
|
|
|
|
if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
|
|
|
|
|
DRM_ERROR("Couldn't disable DPLL0\n");
|
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This
includes:
- Hooking the PCH to the reset logic
- Restoring CDCDLK
- Enabling the DDB power
Among those, only the CDCDLK one is a bit tricky. There's some
complexity in that:
- DPLL0 (which is the source for CDCLK) has two VCOs, each with a set
of supported frequencies. As eDP also uses DPLL0 for its link rate,
once DPLL0 is on, we restrict the possible eDP link rates the chosen
VCO.
- CDCLK also limits the bandwidth available to push pixels.
So, as a first step, this commit restore what the BIOS set, until I can
do more testing.
In case that's of interest for the reviewer, I've unit tested the
function that derives the decimal frequency field:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
static const struct dpll_freq {
unsigned int freq;
unsigned int decimal;
} freqs[] = {
{ .freq = 308570, .decimal = 0b01001100111},
{ .freq = 337500, .decimal = 0b01010100001},
{ .freq = 432000, .decimal = 0b01101011110},
{ .freq = 450000, .decimal = 0b01110000010},
{ .freq = 540000, .decimal = 0b10000110110},
{ .freq = 617140, .decimal = 0b10011010000},
{ .freq = 675000, .decimal = 0b10101000100},
};
static void intbits(unsigned int v)
{
int i;
for(i = 10; i >= 0; i--)
putchar('0' + ((v >> i) & 1));
}
static unsigned int freq_decimal(unsigned int freq /* in kHz */)
{
return (freq - 1000) / 500;
}
static void test_freq(const struct dpll_freq *entry)
{
unsigned int decimal = freq_decimal(entry->freq);
printf("freq: %d, expected: ", entry->freq);
intbits(entry->decimal);
printf(", got: ");
intbits(decimal);
putchar('\n');
assert(decimal == entry->decimal);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < ARRAY_SIZE(freqs); i++)
test_freq(&freqs[i]);
return 0;
}
v2:
- Rebase on top of -nightly
- Use (freq - 1000) / 500 for the decimal frequency (Ville)
- Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville)
- Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to
be consistent with the BXT code (Ville)
- Store boot CDCLK in ddi_pll_init (Ville)
- Merge dev_priv's skl_boot_cdclk into cdclk_freq
- Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville)
- Replace various '0' by SKL_DPLL0 to be a bit more explicit that
we're programming DPLL0
- Busy poll the PCU before doing the frequency change. It takes about
3/4 cycles, each separated by 10us, to get the ACK from the CPU
(Ville)
v3:
- Restore dev_priv->skl_boot_cdclk, leaving unification with
dev_priv->cdclk_freq for a later patch (Daniel, Ville)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-05-21 16:37:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void skl_init_cdclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
unsigned int required_vco;
|
|
|
|
|
|
2015-08-28 16:40:34 +08:00
|
|
|
/* DPLL0 not enabled (happens on early BIOS versions) */
|
|
|
|
|
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
|
|
|
|
|
/* enable DPLL0 */
|
|
|
|
|
required_vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
|
|
|
|
|
skl_dpll0_enable(dev_priv, required_vco);
|
drm/i915/skl: Deinit/init the display at suspend/resume
We need to re-init the display hardware when going out of suspend. This
includes:
- Hooking the PCH to the reset logic
- Restoring CDCDLK
- Enabling the DDB power
Among those, only the CDCDLK one is a bit tricky. There's some
complexity in that:
- DPLL0 (which is the source for CDCLK) has two VCOs, each with a set
of supported frequencies. As eDP also uses DPLL0 for its link rate,
once DPLL0 is on, we restrict the possible eDP link rates the chosen
VCO.
- CDCLK also limits the bandwidth available to push pixels.
So, as a first step, this commit restore what the BIOS set, until I can
do more testing.
In case that's of interest for the reviewer, I've unit tested the
function that derives the decimal frequency field:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
static const struct dpll_freq {
unsigned int freq;
unsigned int decimal;
} freqs[] = {
{ .freq = 308570, .decimal = 0b01001100111},
{ .freq = 337500, .decimal = 0b01010100001},
{ .freq = 432000, .decimal = 0b01101011110},
{ .freq = 450000, .decimal = 0b01110000010},
{ .freq = 540000, .decimal = 0b10000110110},
{ .freq = 617140, .decimal = 0b10011010000},
{ .freq = 675000, .decimal = 0b10101000100},
};
static void intbits(unsigned int v)
{
int i;
for(i = 10; i >= 0; i--)
putchar('0' + ((v >> i) & 1));
}
static unsigned int freq_decimal(unsigned int freq /* in kHz */)
{
return (freq - 1000) / 500;
}
static void test_freq(const struct dpll_freq *entry)
{
unsigned int decimal = freq_decimal(entry->freq);
printf("freq: %d, expected: ", entry->freq);
intbits(entry->decimal);
printf(", got: ");
intbits(decimal);
putchar('\n');
assert(decimal == entry->decimal);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < ARRAY_SIZE(freqs); i++)
test_freq(&freqs[i]);
return 0;
}
v2:
- Rebase on top of -nightly
- Use (freq - 1000) / 500 for the decimal frequency (Ville)
- Fix setting the enable bit of HSW_NDE_RSTWRN_OPT (Ville)
- Rename skl_display_{resume,suspend} to skl_{init,uninit}_cdclk to
be consistent with the BXT code (Ville)
- Store boot CDCLK in ddi_pll_init (Ville)
- Merge dev_priv's skl_boot_cdclk into cdclk_freq
- Use LCPLL_PLL_LOCK instead of (1 << 30) (Ville)
- Replace various '0' by SKL_DPLL0 to be a bit more explicit that
we're programming DPLL0
- Busy poll the PCU before doing the frequency change. It takes about
3/4 cycles, each separated by 10us, to get the ACK from the CPU
(Ville)
v3:
- Restore dev_priv->skl_boot_cdclk, leaving unification with
dev_priv->cdclk_freq for a later patch (Daniel, Ville)
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-05-21 16:37:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set CDCLK to the frequency the BIOS chose */
|
|
|
|
|
skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk);
|
|
|
|
|
|
|
|
|
|
/* enable DBUF power */
|
|
|
|
|
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
|
|
|
|
|
POSTING_READ(DBUF_CTL);
|
|
|
|
|
|
|
|
|
|
udelay(10);
|
|
|
|
|
|
|
|
|
|
if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
|
|
|
|
|
DRM_ERROR("DBuf power enable timeout\n");
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-20 18:13:12 +05:30
|
|
|
int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
|
|
|
|
|
uint32_t cdctl = I915_READ(CDCLK_CTL);
|
|
|
|
|
int freq = dev_priv->skl_boot_cdclk;
|
|
|
|
|
|
2015-11-05 18:05:32 +05:30
|
|
|
/*
|
|
|
|
|
* check if the pre-os intialized the display
|
|
|
|
|
* There is SWF18 scratchpad register defined which is set by the
|
|
|
|
|
* pre-os which can be used by the OS drivers to check the status
|
|
|
|
|
*/
|
|
|
|
|
if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
|
|
|
|
|
goto sanitize;
|
|
|
|
|
|
2015-10-20 18:13:12 +05:30
|
|
|
/* Is PLL enabled and locked ? */
|
|
|
|
|
if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK)))
|
|
|
|
|
goto sanitize;
|
|
|
|
|
|
|
|
|
|
/* DPLL okay; verify the cdclock
|
|
|
|
|
*
|
|
|
|
|
* Noticed in some instances that the freq selection is correct but
|
|
|
|
|
* decimal part is programmed wrong from BIOS where pre-os does not
|
|
|
|
|
* enable display. Verify the same as well.
|
|
|
|
|
*/
|
|
|
|
|
if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq)))
|
|
|
|
|
/* All well; nothing to sanitize */
|
|
|
|
|
return false;
|
|
|
|
|
sanitize:
|
|
|
|
|
/*
|
|
|
|
|
* As of now initialize with max cdclk till
|
|
|
|
|
* we get dynamic cdclk support
|
|
|
|
|
* */
|
|
|
|
|
dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq;
|
|
|
|
|
skl_init_cdclk(dev_priv);
|
|
|
|
|
|
|
|
|
|
/* we did have to sanitize */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 13:48:12 -08:00
|
|
|
/* Adjust CDclk dividers to allow high res or save power if possible */
|
|
|
|
|
static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 val, cmd;
|
|
|
|
|
|
2014-11-24 13:37:41 +05:30
|
|
|
WARN_ON(dev_priv->display.get_display_clock_speed(dev)
|
|
|
|
|
!= dev_priv->cdclk_freq);
|
2014-03-27 17:45:10 +02:00
|
|
|
|
2014-06-13 13:37:47 +03:00
|
|
|
if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
|
2013-11-04 13:48:12 -08:00
|
|
|
cmd = 2;
|
2014-06-13 13:37:47 +03:00
|
|
|
else if (cdclk == 266667)
|
2013-11-04 13:48:12 -08:00
|
|
|
cmd = 1;
|
|
|
|
|
else
|
|
|
|
|
cmd = 0;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
|
|
|
|
|
val &= ~DSPFREQGUAR_MASK;
|
|
|
|
|
val |= (cmd << DSPFREQGUAR_SHIFT);
|
|
|
|
|
vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
|
|
|
|
|
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
|
|
|
|
|
DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
|
|
|
|
|
50)) {
|
|
|
|
|
DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
|
|
}
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
2015-05-26 20:42:31 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
|
2014-06-13 13:37:47 +03:00
|
|
|
if (cdclk == 400000) {
|
2014-10-07 17:41:22 +03:00
|
|
|
u32 divider;
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2014-10-07 17:41:22 +03:00
|
|
|
divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
|
2013-11-04 13:48:12 -08:00
|
|
|
|
|
|
|
|
/* adjust cdclk divider */
|
|
|
|
|
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
|
2015-09-24 23:29:17 +03:00
|
|
|
val &= ~CCK_FREQUENCY_VALUES;
|
2013-11-04 13:48:12 -08:00
|
|
|
val |= divider;
|
|
|
|
|
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
|
2014-06-13 13:37:52 +03:00
|
|
|
|
|
|
|
|
if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
|
2015-09-24 23:29:17 +03:00
|
|
|
CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
|
2014-06-13 13:37:52 +03:00
|
|
|
50))
|
|
|
|
|
DRM_ERROR("timed out waiting for CDclk change\n");
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* adjust self-refresh exit latency value */
|
|
|
|
|
val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
|
|
|
|
|
val &= ~0x7f;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For high bandwidth configs, we set a higher latency in the bunit
|
|
|
|
|
* so that the core display fetch happens in time to avoid underruns.
|
|
|
|
|
*/
|
2014-06-13 13:37:47 +03:00
|
|
|
if (cdclk == 400000)
|
2013-11-04 13:48:12 -08:00
|
|
|
val |= 4500 / 250; /* 4.5 usec */
|
|
|
|
|
else
|
|
|
|
|
val |= 3000 / 250; /* 3.0 usec */
|
|
|
|
|
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
|
2015-05-26 20:42:31 +03:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2015-06-03 15:45:07 +03:00
|
|
|
intel_update_cdclk(dev);
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2014-06-28 02:03:57 +03:00
|
|
|
static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 val, cmd;
|
|
|
|
|
|
2014-11-24 13:37:41 +05:30
|
|
|
WARN_ON(dev_priv->display.get_display_clock_speed(dev)
|
|
|
|
|
!= dev_priv->cdclk_freq);
|
2014-06-28 02:03:57 +03:00
|
|
|
|
|
|
|
|
switch (cdclk) {
|
|
|
|
|
case 333333:
|
|
|
|
|
case 320000:
|
|
|
|
|
case 266667:
|
|
|
|
|
case 200000:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2014-12-08 16:40:10 +01:00
|
|
|
MISSING_CASE(cdclk);
|
2014-06-28 02:03:57 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 20:07:17 +02:00
|
|
|
/*
|
|
|
|
|
* Specs are full of misinformation, but testing on actual
|
|
|
|
|
* hardware has shown that we just need to write the desired
|
|
|
|
|
* CCK divider into the Punit register.
|
|
|
|
|
*/
|
|
|
|
|
cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
|
|
|
|
|
|
2014-06-28 02:03:57 +03:00
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
|
|
|
|
|
val &= ~DSPFREQGUAR_MASK_CHV;
|
|
|
|
|
val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
|
|
|
|
|
vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
|
|
|
|
|
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
|
|
|
|
|
DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
|
|
|
|
|
50)) {
|
|
|
|
|
DRM_ERROR("timed out waiting for CDclk change\n");
|
|
|
|
|
}
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
2015-06-03 15:45:07 +03:00
|
|
|
intel_update_cdclk(dev);
|
2014-06-28 02:03:57 +03:00
|
|
|
}
|
|
|
|
|
|
2013-11-04 13:48:12 -08:00
|
|
|
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
|
|
|
|
|
int max_pixclk)
|
|
|
|
|
{
|
2014-10-07 17:41:22 +03:00
|
|
|
int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 333333 : 320000;
|
2015-03-02 20:07:16 +02:00
|
|
|
int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
|
2014-06-13 13:37:50 +03:00
|
|
|
|
2013-11-04 13:48:12 -08:00
|
|
|
/*
|
|
|
|
|
* Really only a few cases to deal with, as only 4 CDclks are supported:
|
|
|
|
|
* 200MHz
|
|
|
|
|
* 267MHz
|
2014-06-13 13:37:50 +03:00
|
|
|
* 320/333MHz (depends on HPLL freq)
|
2015-03-02 20:07:16 +02:00
|
|
|
* 400MHz (VLV only)
|
|
|
|
|
* So we check to see whether we're above 90% (VLV) or 95% (CHV)
|
|
|
|
|
* of the lower bin and adjust if needed.
|
2014-06-13 13:37:51 +03:00
|
|
|
*
|
|
|
|
|
* We seem to get an unstable or solid color picture at 200MHz.
|
|
|
|
|
* Not sure what's wrong. For now use 200MHz only when all pipes
|
|
|
|
|
* are off.
|
2013-11-04 13:48:12 -08:00
|
|
|
*/
|
2015-03-02 20:07:16 +02:00
|
|
|
if (!IS_CHERRYVIEW(dev_priv) &&
|
|
|
|
|
max_pixclk > freq_320*limit/100)
|
2014-06-13 13:37:47 +03:00
|
|
|
return 400000;
|
2015-03-02 20:07:16 +02:00
|
|
|
else if (max_pixclk > 266667*limit/100)
|
2014-06-13 13:37:50 +03:00
|
|
|
return freq_320;
|
2014-06-13 13:37:51 +03:00
|
|
|
else if (max_pixclk > 0)
|
2014-06-13 13:37:47 +03:00
|
|
|
return 266667;
|
2014-06-13 13:37:51 +03:00
|
|
|
else
|
|
|
|
|
return 200000;
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2014-11-24 13:37:39 +05:30
|
|
|
static int broxton_calc_cdclk(struct drm_i915_private *dev_priv,
|
|
|
|
|
int max_pixclk)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* FIXME:
|
|
|
|
|
* - remove the guardband, it's not needed on BXT
|
|
|
|
|
* - set 19.2MHz bypass frequency if there are no active pipes
|
|
|
|
|
*/
|
|
|
|
|
if (max_pixclk > 576000*9/10)
|
|
|
|
|
return 624000;
|
|
|
|
|
else if (max_pixclk > 384000*9/10)
|
|
|
|
|
return 576000;
|
|
|
|
|
else if (max_pixclk > 288000*9/10)
|
|
|
|
|
return 384000;
|
|
|
|
|
else if (max_pixclk > 144000*9/10)
|
|
|
|
|
return 288000;
|
|
|
|
|
else
|
|
|
|
|
return 144000;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:23 +03:00
|
|
|
/* Compute the max pixel clock for new configuration. Uses atomic state if
|
|
|
|
|
* that's non-NULL, look at current state otherwise. */
|
|
|
|
|
static int intel_mode_max_pixclk(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *state)
|
2013-11-04 13:48:12 -08:00
|
|
|
{
|
2015-12-10 12:33:57 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
unsigned max_pixclk = 0, i;
|
|
|
|
|
enum pipe pipe;
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
|
|
sizeof(intel_state->min_pixclk));
|
2015-04-02 14:47:56 +03:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
int pixclk = 0;
|
|
|
|
|
|
|
|
|
|
if (crtc_state->enable)
|
|
|
|
|
pixclk = crtc_state->adjusted_mode.crtc_clock;
|
2015-04-02 14:47:56 +03:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
intel_state->min_pixclk[i] = pixclk;
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (!intel_state->active_crtcs)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for_each_pipe(dev_priv, pipe)
|
|
|
|
|
max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
|
|
|
|
|
|
2013-11-04 13:48:12 -08:00
|
|
|
return max_pixclk;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
|
2013-11-04 13:48:12 -08:00
|
|
|
{
|
2015-06-15 12:33:56 +02:00
|
|
|
struct drm_device *dev = state->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int max_pixclk = intel_mode_max_pixclk(dev, state);
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *intel_state =
|
|
|
|
|
to_intel_atomic_state(state);
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2015-04-02 14:47:56 +03:00
|
|
|
if (max_pixclk < 0)
|
|
|
|
|
return max_pixclk;
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
intel_state->cdclk = intel_state->dev_cdclk =
|
2015-06-15 12:33:56 +02:00
|
|
|
valleyview_calc_cdclk(dev_priv, max_pixclk);
|
2015-04-21 17:13:04 +03:00
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
if (!intel_state->active_crtcs)
|
|
|
|
|
intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-04-02 14:47:56 +03:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static int broxton_modeset_calc_cdclk(struct drm_atomic_state *state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = state->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int max_pixclk = intel_mode_max_pixclk(dev, state);
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *intel_state =
|
|
|
|
|
to_intel_atomic_state(state);
|
2015-06-01 12:49:53 +02:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
if (max_pixclk < 0)
|
|
|
|
|
return max_pixclk;
|
2015-06-01 12:49:53 +02:00
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
intel_state->cdclk = intel_state->dev_cdclk =
|
2015-06-15 12:33:56 +02:00
|
|
|
broxton_calc_cdclk(dev_priv, max_pixclk);
|
2015-06-01 12:49:53 +02:00
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
if (!intel_state->active_crtcs)
|
|
|
|
|
intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, 0);
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
return 0;
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2015-03-05 21:19:50 +02:00
|
|
|
static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
unsigned int credits, default_credits;
|
|
|
|
|
|
|
|
|
|
if (IS_CHERRYVIEW(dev_priv))
|
|
|
|
|
default_credits = PFI_CREDIT(12);
|
|
|
|
|
else
|
|
|
|
|
default_credits = PFI_CREDIT(8);
|
|
|
|
|
|
2015-09-24 23:29:18 +03:00
|
|
|
if (dev_priv->cdclk_freq >= dev_priv->czclk_freq) {
|
2015-03-05 21:19:50 +02:00
|
|
|
/* CHV suggested value is 31 or 63 */
|
|
|
|
|
if (IS_CHERRYVIEW(dev_priv))
|
2015-05-26 20:22:40 +03:00
|
|
|
credits = PFI_CREDIT_63;
|
2015-03-05 21:19:50 +02:00
|
|
|
else
|
|
|
|
|
credits = PFI_CREDIT(15);
|
|
|
|
|
} else {
|
|
|
|
|
credits = default_credits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* WA - write default credits before re-programming
|
|
|
|
|
* FIXME: should we also set the resend bit here?
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
|
|
|
|
|
default_credits);
|
|
|
|
|
|
|
|
|
|
I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
|
|
|
|
|
credits | PFI_CREDIT_RESEND);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME is this guaranteed to clear
|
|
|
|
|
* immediately or should we poll for it?
|
|
|
|
|
*/
|
|
|
|
|
WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
2013-11-04 13:48:12 -08:00
|
|
|
{
|
2015-04-21 17:13:23 +03:00
|
|
|
struct drm_device *dev = old_state->dev;
|
2013-11-04 13:48:12 -08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *old_intel_state =
|
|
|
|
|
to_intel_atomic_state(old_state);
|
|
|
|
|
unsigned req_cdclk = old_intel_state->dev_cdclk;
|
2013-11-04 13:48:12 -08:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
/*
|
|
|
|
|
* FIXME: We can end up here with all power domains off, yet
|
|
|
|
|
* with a CDCLK frequency other than the minimum. To account
|
|
|
|
|
* for this take the PIPE-A power domain, which covers the HW
|
|
|
|
|
* blocks needed for the following programming. This can be
|
|
|
|
|
* removed once it's guaranteed that we get here either with
|
|
|
|
|
* the minimum CDCLK set, or the required power domains
|
|
|
|
|
* enabled.
|
|
|
|
|
*/
|
|
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
|
2014-11-19 16:25:37 +02:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
if (IS_CHERRYVIEW(dev))
|
|
|
|
|
cherryview_set_cdclk(dev, req_cdclk);
|
|
|
|
|
else
|
|
|
|
|
valleyview_set_cdclk(dev, req_cdclk);
|
2014-11-19 16:25:37 +02:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
vlv_program_pfi_credits(dev_priv);
|
2015-03-05 21:19:50 +02:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
|
2013-11-04 13:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
static void valleyview_crtc_enable(struct drm_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2014-09-30 10:56:47 +02:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2013-04-18 14:51:36 -07:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
|
2015-06-01 12:49:52 +02:00
|
|
|
if (WARN_ON(intel_crtc->active))
|
2013-04-18 14:51:36 -07:00
|
|
|
return;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_dp_encoder)
|
2015-02-13 15:32:59 +05:30
|
|
|
intel_dp_set_m_n(intel_crtc, M1_N1);
|
2014-04-24 23:55:06 +02:00
|
|
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc);
|
|
|
|
|
|
2014-10-16 20:52:34 +03:00
|
|
|
if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
|
|
|
|
|
I915_WRITE(CHV_CANVAS(pipe), 0);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:55:06 +02:00
|
|
|
i9xx_set_pipeconf(intel_crtc);
|
|
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
intel_crtc->active = true;
|
|
|
|
|
|
2014-09-30 10:56:47 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
2014-05-16 19:40:25 +03:00
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->pre_pll_enable)
|
|
|
|
|
encoder->pre_pll_enable(encoder);
|
|
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder) {
|
2015-07-08 23:45:52 +03:00
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
|
|
|
|
chv_prepare_pll(intel_crtc, intel_crtc->config);
|
2015-01-15 14:55:25 +02:00
|
|
|
chv_enable_pll(intel_crtc, intel_crtc->config);
|
2015-07-08 23:45:52 +03:00
|
|
|
} else {
|
|
|
|
|
vlv_prepare_pll(intel_crtc, intel_crtc->config);
|
2015-01-15 14:55:25 +02:00
|
|
|
vlv_enable_pll(intel_crtc, intel_crtc->config);
|
2015-07-08 23:45:52 +03:00
|
|
|
}
|
2014-05-02 14:27:47 +03:00
|
|
|
}
|
2013-04-18 14:51:36 -07:00
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
|
2013-04-25 12:55:01 -07:00
|
|
|
i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
|
2013-06-04 13:48:59 +03:00
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
|
2014-01-17 13:51:12 -02:00
|
|
|
intel_enable_pipe(intel_crtc);
|
2014-04-15 18:41:22 +02:00
|
|
|
|
2014-08-14 22:04:37 +03:00
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
encoder->enable(encoder);
|
2013-04-18 14:51:36 -07:00
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:55:10 +02:00
|
|
|
static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
I915_WRITE(FP0(crtc->pipe), crtc->config->dpll_hw_state.fp0);
|
|
|
|
|
I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1);
|
2014-04-24 23:55:10 +02:00
|
|
|
}
|
|
|
|
|
|
2010-09-10 10:31:34 -07: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-07 14:24:08 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
2014-09-30 10:56:47 +02:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(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-07 14:24:08 -08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-06-29 22:40:09 +02: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-07 14:24:08 -08:00
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
|
|
|
2015-06-01 12:49:52 +02:00
|
|
|
if (WARN_ON(intel_crtc->active))
|
2010-09-13 14:19:16 +01:00
|
|
|
return;
|
|
|
|
|
|
2014-04-24 23:55:10 +02:00
|
|
|
i9xx_set_pll_dividers(intel_crtc);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->has_dp_encoder)
|
2015-02-13 15:32:59 +05:30
|
|
|
intel_dp_set_m_n(intel_crtc, M1_N1);
|
2014-04-24 23:55:06 +02:00
|
|
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc);
|
|
|
|
|
|
|
|
|
|
i9xx_set_pipeconf(intel_crtc);
|
|
|
|
|
|
2010-09-13 14:19:16 +01:00
|
|
|
intel_crtc->active = true;
|
2010-09-13 13:54:26 +01:00
|
|
|
|
2014-05-16 19:40:25 +03:00
|
|
|
if (!IS_GEN2(dev))
|
2014-09-30 10:56:47 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
2014-05-16 19:40:25 +03:00
|
|
|
|
2013-02-08 16:35:38 +02:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->pre_enable)
|
|
|
|
|
encoder->pre_enable(encoder);
|
|
|
|
|
|
2013-06-05 13:34:30 +02:00
|
|
|
i9xx_enable_pll(intel_crtc);
|
|
|
|
|
|
2013-04-25 12:55:01 -07:00
|
|
|
i9xx_pfit_enable(intel_crtc);
|
|
|
|
|
|
2013-06-04 13:48:59 +03:00
|
|
|
intel_crtc_load_lut(crtc);
|
|
|
|
|
|
2013-09-10 11:39:55 +03:00
|
|
|
intel_update_watermarks(crtc);
|
2014-01-17 13:51:12 -02:00
|
|
|
intel_enable_pipe(intel_crtc);
|
2014-04-15 18:41:22 +02:00
|
|
|
|
2014-08-14 22:04:37 +03:00
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
encoder->enable(encoder);
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_enable(intel_crtc);
|
2010-09-10 10:31:34 -07: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-07 14:24:08 -08:00
|
|
|
|
2013-04-11 16:29:06 +02: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;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (!crtc->config->gmch_pfit.control)
|
2013-05-08 10:36:31 +02:00
|
|
|
return;
|
2013-04-11 16:29:06 +02:00
|
|
|
|
2013-05-08 10:36:31 +02:00
|
|
|
assert_pipe_disabled(dev_priv, crtc->pipe);
|
2013-04-11 16:29:06 +02:00
|
|
|
|
2013-05-08 10:36:31 +02:00
|
|
|
DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
|
|
|
|
|
I915_READ(PFIT_CONTROL));
|
|
|
|
|
I915_WRITE(PFIT_CONTROL, 0);
|
2013-04-11 16:29:06 +02:00
|
|
|
}
|
|
|
|
|
|
2010-09-10 10:31:34 -07: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-29 22:40:09 +02:00
|
|
|
struct intel_encoder *encoder;
|
2010-09-10 10:31:34 -07:00
|
|
|
int pipe = intel_crtc->pipe;
|
2012-06-29 22:40:09 +02:00
|
|
|
|
2014-04-25 13:30:12 +03:00
|
|
|
/*
|
|
|
|
|
* On gen2 planes are double buffered but the pipe isn't, so we must
|
|
|
|
|
* wait for planes to fully turn off before disabling the pipe.
|
2014-06-13 14:54:21 +03:00
|
|
|
* We also need to wait on all gmch platforms because of the
|
|
|
|
|
* self-refresh mode constraint explained above.
|
2014-04-25 13:30:12 +03:00
|
|
|
*/
|
2014-06-13 14:54:21 +03:00
|
|
|
intel_wait_for_vblank(dev, pipe);
|
2014-04-25 13:30:12 +03:00
|
|
|
|
2014-08-14 22:04:37 +03:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
encoder->disable(encoder);
|
|
|
|
|
|
2015-01-07 13:54:39 +01:00
|
|
|
drm_crtc_vblank_off(crtc);
|
|
|
|
|
assert_vblank_disabled(crtc);
|
|
|
|
|
|
2014-08-15 01:21:56 +03:00
|
|
|
intel_disable_pipe(intel_crtc);
|
2013-02-08 16:35:37 +02:00
|
|
|
|
2013-04-11 16:29:06 +02:00
|
|
|
i9xx_pfit_disable(intel_crtc);
|
2013-02-08 16:35:37 +02:00
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->post_disable)
|
|
|
|
|
encoder->post_disable(encoder);
|
|
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (!intel_crtc->config->has_dsi_encoder) {
|
2014-04-09 13:28:17 +03:00
|
|
|
if (IS_CHERRYVIEW(dev))
|
|
|
|
|
chv_disable_pll(dev_priv, pipe);
|
|
|
|
|
else if (IS_VALLEYVIEW(dev))
|
|
|
|
|
vlv_disable_pll(dev_priv, pipe);
|
|
|
|
|
else
|
2014-09-05 21:52:42 +03:00
|
|
|
i9xx_disable_pll(intel_crtc);
|
2014-04-09 13:28:17 +03:00
|
|
|
}
|
2010-09-10 10:31:34 -07:00
|
|
|
|
2015-07-08 23:45:49 +03:00
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
|
|
if (encoder->post_pll_disable)
|
|
|
|
|
encoder->post_pll_disable(encoder);
|
|
|
|
|
|
2014-05-16 19:40:25 +03:00
|
|
|
if (!IS_GEN2(dev))
|
2014-09-30 10:56:47 +02:00
|
|
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
|
2015-10-15 10:44:46 -03:00
|
|
|
|
|
|
|
|
intel_fbc_disable_crtc(intel_crtc);
|
2010-09-10 10:31:34 -07:00
|
|
|
}
|
|
|
|
|
|
2015-06-12 11:15:39 +02:00
|
|
|
static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
|
|
|
|
enum intel_display_power_domain domain;
|
|
|
|
|
unsigned long domains;
|
|
|
|
|
|
|
|
|
|
if (!intel_crtc->active)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-06-15 12:33:52 +02:00
|
|
|
if (to_intel_plane_state(crtc->primary->state)->visible) {
|
2015-10-19 17:09:23 +02:00
|
|
|
WARN_ON(intel_crtc->unpin_work);
|
|
|
|
|
|
2015-06-15 12:33:52 +02:00
|
|
|
intel_pre_disable_primary(crtc);
|
2015-11-23 10:25:28 +01:00
|
|
|
|
|
|
|
|
intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
|
|
|
|
|
to_intel_plane_state(crtc->primary->state)->visible = false;
|
2015-06-15 12:33:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-12 11:15:39 +02:00
|
|
|
dev_priv->display.crtc_disable(crtc);
|
2015-09-24 15:53:06 -07:00
|
|
|
intel_crtc->active = false;
|
|
|
|
|
intel_update_watermarks(crtc);
|
2015-07-13 11:55:05 +02:00
|
|
|
intel_disable_shared_dpll(intel_crtc);
|
2015-06-12 11:15:39 +02:00
|
|
|
|
|
|
|
|
domains = intel_crtc->enabled_power_domains;
|
|
|
|
|
for_each_power_domain(domain, domains)
|
|
|
|
|
intel_display_power_put(dev_priv, domain);
|
|
|
|
|
intel_crtc->enabled_power_domains = 0;
|
2015-12-10 12:33:57 +01:00
|
|
|
|
|
|
|
|
dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
|
|
|
|
|
dev_priv->min_pixclk[intel_crtc->pipe] = 0;
|
2015-06-12 11:15:39 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-01 12:49:47 +02:00
|
|
|
/*
|
|
|
|
|
* turn all crtc's off, but do not adjust state
|
|
|
|
|
* This has to be paired with a call to intel_modeset_setup_hw_state.
|
|
|
|
|
*/
|
2015-07-13 16:30:29 +02:00
|
|
|
int intel_display_suspend(struct drm_device *dev)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2015-07-13 16:30:29 +02:00
|
|
|
struct drm_mode_config *config = &dev->mode_config;
|
|
|
|
|
struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
|
|
|
|
|
struct drm_atomic_state *state;
|
2015-06-01 12:49:47 +02:00
|
|
|
struct drm_crtc *crtc;
|
2015-07-13 16:30:29 +02:00
|
|
|
unsigned crtc_mask = 0;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (WARN_ON(!ctx))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
lockdep_assert_held(&ctx->ww_ctx);
|
|
|
|
|
state = drm_atomic_state_alloc(dev);
|
|
|
|
|
if (WARN_ON(!state))
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
state->acquire_ctx = ctx;
|
|
|
|
|
state->allow_modeset = true;
|
|
|
|
|
|
|
|
|
|
for_each_crtc(dev, crtc) {
|
|
|
|
|
struct drm_crtc_state *crtc_state =
|
|
|
|
|
drm_atomic_get_crtc_state(state, crtc);
|
2015-06-01 12:49:47 +02:00
|
|
|
|
2015-07-13 16:30:29 +02:00
|
|
|
ret = PTR_ERR_OR_ZERO(crtc_state);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto free;
|
|
|
|
|
|
|
|
|
|
if (!crtc_state->active)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
crtc_state->active = false;
|
|
|
|
|
crtc_mask |= 1 << drm_crtc_index(crtc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (crtc_mask) {
|
2015-07-13 16:30:30 +02:00
|
|
|
ret = drm_atomic_commit(state);
|
2015-07-13 16:30:29 +02:00
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
|
for_each_crtc(dev, crtc)
|
|
|
|
|
if (crtc_mask & (1 << drm_crtc_index(crtc)))
|
|
|
|
|
crtc->state->active = true;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free:
|
|
|
|
|
if (ret)
|
|
|
|
|
DRM_ERROR("Suspending crtc's failed with %i\n", ret);
|
|
|
|
|
drm_atomic_state_free(state);
|
|
|
|
|
return ret;
|
2012-04-20 17:11:53 +01:00
|
|
|
}
|
|
|
|
|
|
2010-08-04 13:50:23 +01:00
|
|
|
void intel_encoder_destroy(struct drm_encoder *encoder)
|
2010-09-10 10:47:20 -07:00
|
|
|
{
|
2010-09-09 15:14:28 +01:00
|
|
|
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
2010-08-04 13:50:23 +01:00
|
|
|
|
|
|
|
|
drm_encoder_cleanup(encoder);
|
|
|
|
|
kfree(intel_encoder);
|
2010-09-10 10:47:20 -07:00
|
|
|
}
|
|
|
|
|
|
2012-07-02 21:54:27 +02:00
|
|
|
/* Cross check the actual hw state with our own modeset state tracking (and it's
|
|
|
|
|
* internal consistency). */
|
2012-08-31 17:37:33 +02: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-07 14:24:08 -08:00
|
|
|
{
|
2015-08-06 13:49:22 +02:00
|
|
|
struct drm_crtc *crtc = connector->base.state->crtc;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
|
|
|
|
connector->base.base.id,
|
|
|
|
|
connector->base.name);
|
|
|
|
|
|
2012-07-02 21:54:27 +02:00
|
|
|
if (connector->get_hw_state(connector)) {
|
2015-08-27 13:13:31 +02:00
|
|
|
struct intel_encoder *encoder = connector->encoder;
|
2015-08-06 13:49:22 +02:00
|
|
|
struct drm_connector_state *conn_state = connector->base.state;
|
2012-07-02 21:54:27 +02:00
|
|
|
|
2015-08-06 13:49:22 +02:00
|
|
|
I915_STATE_WARN(!crtc,
|
|
|
|
|
"connector enabled without attached crtc\n");
|
2012-07-02 21:54:27 +02:00
|
|
|
|
2015-08-06 13:49:22 +02:00
|
|
|
if (!crtc)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
I915_STATE_WARN(!crtc->state->active,
|
|
|
|
|
"connector is active, but attached crtc isn't\n");
|
|
|
|
|
|
2015-08-27 13:13:31 +02:00
|
|
|
if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
|
2015-08-06 13:49:22 +02:00
|
|
|
return;
|
|
|
|
|
|
2015-08-27 13:13:31 +02:00
|
|
|
I915_STATE_WARN(conn_state->best_encoder != &encoder->base,
|
2015-08-06 13:49:22 +02:00
|
|
|
"atomic encoder doesn't match attached encoder\n");
|
|
|
|
|
|
2015-08-27 13:13:31 +02:00
|
|
|
I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
|
2015-08-06 13:49:22 +02:00
|
|
|
"attached encoder crtc differs from connector crtc\n");
|
|
|
|
|
} else {
|
2015-08-05 12:37:06 +02:00
|
|
|
I915_STATE_WARN(crtc && crtc->state->active,
|
|
|
|
|
"attached crtc is active, but connector isn't\n");
|
2015-08-06 13:49:22 +02:00
|
|
|
I915_STATE_WARN(!crtc && connector->base.state->best_encoder,
|
|
|
|
|
"best encoder set without crtc!\n");
|
2012-07-02 21:54:27 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-04-10 10:59:10 +03:00
|
|
|
int intel_connector_init(struct intel_connector *connector)
|
|
|
|
|
{
|
|
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
|
|
|
|
|
connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL);
|
|
|
|
|
if (!connector_state)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
connector->base.state = connector_state;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct intel_connector *intel_connector_alloc(void)
|
|
|
|
|
{
|
|
|
|
|
struct intel_connector *connector;
|
|
|
|
|
|
|
|
|
|
connector = kzalloc(sizeof *connector, GFP_KERNEL);
|
|
|
|
|
if (!connector)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (intel_connector_init(connector) < 0) {
|
|
|
|
|
kfree(connector);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return connector;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-02 13:10:34 +02: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 13:50:23 +01: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-02 20:28:59 +02:00
|
|
|
enum pipe pipe = 0;
|
2012-07-02 13:10:34 +02:00
|
|
|
struct intel_encoder *encoder = connector->encoder;
|
2010-08-04 13:50:23 +01:00
|
|
|
|
2012-07-02 13:10:34 +02:00
|
|
|
return encoder->get_hw_state(encoder, &pipe);
|
2010-08-04 13:50:23 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-30 08:33:12 +03:00
|
|
|
static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
|
2015-03-11 18:52:31 +02:00
|
|
|
{
|
2015-03-30 08:33:12 +03:00
|
|
|
if (crtc_state->base.enable && crtc_state->has_pch_encoder)
|
|
|
|
|
return crtc_state->fdi_lanes;
|
2015-03-11 18:52:31 +02:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 08:33:12 +03:00
|
|
|
static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-04-29 19:34:16 +02:00
|
|
|
{
|
2015-03-30 08:33:12 +03:00
|
|
|
struct drm_atomic_state *state = pipe_config->base.state;
|
|
|
|
|
struct intel_crtc *other_crtc;
|
|
|
|
|
struct intel_crtc_state *other_crtc_state;
|
|
|
|
|
|
2013-04-29 19:34:16 +02:00
|
|
|
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);
|
2015-03-30 08:33:12 +03:00
|
|
|
return -EINVAL;
|
2013-04-29 19:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-02 21:07:44 -07:00
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
2013-04-29 19:34:16 +02:00
|
|
|
if (pipe_config->fdi_lanes > 2) {
|
|
|
|
|
DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
|
|
|
|
|
pipe_config->fdi_lanes);
|
2015-03-30 08:33:12 +03:00
|
|
|
return -EINVAL;
|
2013-04-29 19:34:16 +02:00
|
|
|
} else {
|
2015-03-30 08:33:12 +03:00
|
|
|
return 0;
|
2013-04-29 19:34:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->num_pipes == 2)
|
2015-03-30 08:33:12 +03:00
|
|
|
return 0;
|
2013-04-29 19:34:16 +02:00
|
|
|
|
|
|
|
|
/* Ivybridge 3 pipe is really complicated */
|
|
|
|
|
switch (pipe) {
|
|
|
|
|
case PIPE_A:
|
2015-03-30 08:33:12 +03:00
|
|
|
return 0;
|
2013-04-29 19:34:16 +02:00
|
|
|
case PIPE_B:
|
2015-03-30 08:33:12 +03:00
|
|
|
if (pipe_config->fdi_lanes <= 2)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_C));
|
|
|
|
|
other_crtc_state =
|
|
|
|
|
intel_atomic_get_crtc_state(state, other_crtc);
|
|
|
|
|
if (IS_ERR(other_crtc_state))
|
|
|
|
|
return PTR_ERR(other_crtc_state);
|
|
|
|
|
|
|
|
|
|
if (pipe_required_fdi_lanes(other_crtc_state) > 0) {
|
2013-04-29 19:34:16 +02:00
|
|
|
DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
|
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
2015-03-30 08:33:12 +03:00
|
|
|
return -EINVAL;
|
2013-04-29 19:34:16 +02:00
|
|
|
}
|
2015-03-30 08:33:12 +03:00
|
|
|
return 0;
|
2013-04-29 19:34:16 +02:00
|
|
|
case PIPE_C:
|
2015-03-11 18:52:30 +02:00
|
|
|
if (pipe_config->fdi_lanes > 2) {
|
|
|
|
|
DRM_DEBUG_KMS("only 2 lanes on pipe %c: required %i lanes\n",
|
|
|
|
|
pipe_name(pipe), pipe_config->fdi_lanes);
|
2015-03-30 08:33:12 +03:00
|
|
|
return -EINVAL;
|
2015-03-11 18:52:30 +02:00
|
|
|
}
|
2015-03-30 08:33:12 +03:00
|
|
|
|
|
|
|
|
other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_B));
|
|
|
|
|
other_crtc_state =
|
|
|
|
|
intel_atomic_get_crtc_state(state, other_crtc);
|
|
|
|
|
if (IS_ERR(other_crtc_state))
|
|
|
|
|
return PTR_ERR(other_crtc_state);
|
|
|
|
|
|
|
|
|
|
if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
|
2013-04-29 19:34:16 +02:00
|
|
|
DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
|
2015-03-30 08:33:12 +03:00
|
|
|
return -EINVAL;
|
2013-04-29 19:34:16 +02:00
|
|
|
}
|
2015-03-30 08:33:12 +03:00
|
|
|
return 0;
|
2013-04-29 19:34:16 +02:00
|
|
|
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 00:00:16 +01:00
|
|
|
#define RETRY 1
|
|
|
|
|
static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-04-19 11:24:43 +02:00
|
|
|
{
|
2013-04-29 19:34:16 +02:00
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
2015-09-08 13:40:49 +03:00
|
|
|
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
|
2015-03-30 08:33:12 +03:00
|
|
|
int lane, link_bw, fdi_dotclock, ret;
|
|
|
|
|
bool needs_recompute = false;
|
2013-04-19 11:24:43 +02: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 00:00:16 +01:00
|
|
|
retry:
|
2013-04-19 11:24:43 +02: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;
|
|
|
|
|
|
2013-09-25 16:45:37 +01:00
|
|
|
fdi_dotclock = adjusted_mode->crtc_clock;
|
2013-04-19 11:24:43 +02:00
|
|
|
|
drm/i915: clear up the fdi dotclock semantics for M/N computation
We currently mutliply the link_bw of the fdi link with the pixel
multiplier, which is wrong: The FDI link doesn't suddenly grow more
bandwidth. In reality the pixel mutliplication only happens in the PCH,
before the pixels are fed into the port.
But since we our code treats the uses the target clock after pixels
are doubled (tripled, ...) already, we need to correct this.
Semantically it's clearer to divide the target clock to get the fdi
dotclock instead of multiplying the bw, so do that instead.
Note that the target clock is already multiplied by the same factor,
so the division will never loose accuracy for the M/N computation.
The lane computation otoh used the wrong value, we also need to feed
the fdi dotclock to that.
Split out on a request from Paulo Zanoni.
v2: Also fix the lane computation, it used the target clock to compute
the bw requirements, not the fdi dotclock (i.e. adjusted with the
pixel multiplier). Since sdvo only uses the pixel multiplier for
low-res modes (with a dotclock below 100MHz) we wouldn't ever have
rejected a bogus mode, but just used an inefficient fdi config.
v3: Amend the commit message to explain better what the change for the
fdi lane config computation is all about. Requested by Paulo.
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-06-01 17:16:19 +02:00
|
|
|
lane = ironlake_get_lanes_required(fdi_dotclock, link_bw,
|
2013-04-19 11:24:43 +02:00
|
|
|
pipe_config->pipe_bpp);
|
|
|
|
|
|
|
|
|
|
pipe_config->fdi_lanes = lane;
|
|
|
|
|
|
drm/i915: clear up the fdi dotclock semantics for M/N computation
We currently mutliply the link_bw of the fdi link with the pixel
multiplier, which is wrong: The FDI link doesn't suddenly grow more
bandwidth. In reality the pixel mutliplication only happens in the PCH,
before the pixels are fed into the port.
But since we our code treats the uses the target clock after pixels
are doubled (tripled, ...) already, we need to correct this.
Semantically it's clearer to divide the target clock to get the fdi
dotclock instead of multiplying the bw, so do that instead.
Note that the target clock is already multiplied by the same factor,
so the division will never loose accuracy for the M/N computation.
The lane computation otoh used the wrong value, we also need to feed
the fdi dotclock to that.
Split out on a request from Paulo Zanoni.
v2: Also fix the lane computation, it used the target clock to compute
the bw requirements, not the fdi dotclock (i.e. adjusted with the
pixel multiplier). Since sdvo only uses the pixel multiplier for
low-res modes (with a dotclock below 100MHz) we wouldn't ever have
rejected a bogus mode, but just used an inefficient fdi config.
v3: Amend the commit message to explain better what the change for the
fdi lane config computation is all about. Requested by Paulo.
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-06-01 17:16:19 +02:00
|
|
|
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
|
2013-04-19 11:24:43 +02:00
|
|
|
link_bw, &pipe_config->fdi_m_n);
|
2013-04-29 19:34:16 +02:00
|
|
|
|
2015-03-30 08:33:12 +03:00
|
|
|
ret = ironlake_check_fdi_lanes(intel_crtc->base.dev,
|
|
|
|
|
intel_crtc->pipe, pipe_config);
|
|
|
|
|
if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
|
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 00:00:16 +01:00
|
|
|
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;
|
|
|
|
|
|
2015-03-30 08:33:12 +03:00
|
|
|
return ret;
|
2013-04-19 11:24:43 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-03 15:45:11 +03:00
|
|
|
static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_crtc_state *pipe_config)
|
|
|
|
|
{
|
|
|
|
|
if (pipe_config->pipe_bpp > 24)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* HSW can handle pixel rate up to cdclk? */
|
|
|
|
|
if (IS_HASWELL(dev_priv->dev))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/*
|
2015-06-03 15:45:13 +03:00
|
|
|
* We compare against max which means we must take
|
|
|
|
|
* the increased cdclk requirement into account when
|
|
|
|
|
* calculating the new cdclk.
|
|
|
|
|
*
|
|
|
|
|
* Should measure whether using a lower cdclk w/o IPS
|
2015-06-03 15:45:11 +03:00
|
|
|
*/
|
|
|
|
|
return ilk_pipe_pixel_rate(pipe_config) <=
|
|
|
|
|
dev_priv->max_cdclk_freq * 95 / 100;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-31 16:33:22 -03:00
|
|
|
static void hsw_compute_ips_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-05-31 16:33:22 -03:00
|
|
|
{
|
2015-06-03 15:45:11 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2014-01-21 11:24:25 +02:00
|
|
|
pipe_config->ips_enabled = i915.enable_ips &&
|
2015-06-03 15:45:11 +03:00
|
|
|
hsw_crtc_supports_ips(crtc) &&
|
|
|
|
|
pipe_config_supports_ips(dev_priv, pipe_config);
|
2013-05-31 16:33:22 -03:00
|
|
|
}
|
|
|
|
|
|
2015-10-30 23:39:38 +02:00
|
|
|
static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
|
|
|
|
|
|
|
|
|
/* GDG double wide on either pipe, otherwise pipe A only */
|
|
|
|
|
return INTEL_INFO(dev_priv)->gen < 4 &&
|
|
|
|
|
(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-07 23:10:32 +02:00
|
|
|
static int intel_crtc_compute_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *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-07 14:24:08 -08:00
|
|
|
{
|
2013-06-07 23:10:32 +02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2014-10-29 11:32:33 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-09-08 13:40:49 +03:00
|
|
|
const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
|
2010-09-12 18:25:19 +01:00
|
|
|
|
2013-09-04 18:30:04 +03:00
|
|
|
/* FIXME should check pixel clock limits on all platforms */
|
2013-09-04 18:30:02 +03:00
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
2015-10-30 23:39:38 +02:00
|
|
|
int clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
|
2013-09-04 18:30:02 +03:00
|
|
|
|
|
|
|
|
/*
|
2015-10-30 23:39:38 +02:00
|
|
|
* Enable double wide mode when the dot clock
|
2013-09-04 18:30:02 +03:00
|
|
|
* is > 90% of the (display) core speed.
|
|
|
|
|
*/
|
2015-10-30 23:39:38 +02:00
|
|
|
if (intel_crtc_supports_double_wide(crtc) &&
|
|
|
|
|
adjusted_mode->crtc_clock > clock_limit) {
|
2013-09-04 18:30:04 +03:00
|
|
|
clock_limit *= 2;
|
2013-09-04 18:30:02 +03:00
|
|
|
pipe_config->double_wide = true;
|
2013-09-04 18:30:04 +03:00
|
|
|
}
|
|
|
|
|
|
2015-10-30 23:39:38 +02:00
|
|
|
if (adjusted_mode->crtc_clock > clock_limit) {
|
|
|
|
|
DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
|
|
|
|
|
adjusted_mode->crtc_clock, clock_limit,
|
|
|
|
|
yesno(pipe_config->double_wide));
|
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 00:00:16 +01:00
|
|
|
return -EINVAL;
|
2015-10-30 23:39:38 +02:00
|
|
|
}
|
2009-06-05 15:38:42 +08:00
|
|
|
}
|
2010-09-12 18:25:19 +01:00
|
|
|
|
2013-09-04 18:30:05 +03:00
|
|
|
/*
|
|
|
|
|
* Pipe horizontal size must be even in:
|
|
|
|
|
* - DVO ganged mode
|
|
|
|
|
* - LVDS dual channel mode
|
|
|
|
|
* - Double wide pipe
|
|
|
|
|
*/
|
2015-03-20 16:18:17 +02:00
|
|
|
if ((intel_pipe_will_have_type(pipe_config, INTEL_OUTPUT_LVDS) &&
|
2013-09-04 18:30:05 +03:00
|
|
|
intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
|
|
|
|
|
pipe_config->pipe_src_w &= ~1;
|
|
|
|
|
|
2013-05-03 18:48:11 +01:00
|
|
|
/* Cantiga+ cannot handle modes with a hsync front porch of 0.
|
|
|
|
|
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
|
2012-06-21 13:19:59 +03:00
|
|
|
*/
|
|
|
|
|
if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
|
2015-09-25 16:38:56 +03:00
|
|
|
adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_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 00:00:16 +01:00
|
|
|
return -EINVAL;
|
2012-06-21 13:19:59 +03:00
|
|
|
|
2013-06-24 18:29:34 +01:00
|
|
|
if (HAS_IPS(dev))
|
2013-06-07 23:10:32 +02:00
|
|
|
hsw_compute_ips_config(crtc, pipe_config);
|
|
|
|
|
|
2013-04-19 11:24:43 +02:00
|
|
|
if (pipe_config->has_pch_encoder)
|
2013-06-07 23:10:32 +02:00
|
|
|
return ironlake_fdi_compute_config(crtc, pipe_config);
|
2013-04-19 11:24:43 +02:00
|
|
|
|
2015-06-15 12:33:41 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-03-31 14:12:01 +03:00
|
|
|
static int skylake_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
|
|
|
|
|
uint32_t cdctl = I915_READ(CDCLK_CTL);
|
|
|
|
|
uint32_t linkrate;
|
|
|
|
|
|
2015-06-04 18:21:31 +01:00
|
|
|
if (!(lcpll1 & LCPLL_PLL_ENABLE))
|
2015-03-31 14:12:01 +03:00
|
|
|
return 24000; /* 24MHz is the cd freq with NSSC ref */
|
|
|
|
|
|
|
|
|
|
if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540)
|
|
|
|
|
return 540000;
|
|
|
|
|
|
|
|
|
|
linkrate = (I915_READ(DPLL_CTRL1) &
|
2015-04-30 16:39:17 +01:00
|
|
|
DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1;
|
2015-03-31 14:12:01 +03:00
|
|
|
|
2015-04-30 16:39:17 +01:00
|
|
|
if (linkrate == DPLL_CTRL1_LINK_RATE_2160 ||
|
|
|
|
|
linkrate == DPLL_CTRL1_LINK_RATE_1080) {
|
2015-03-31 14:12:01 +03:00
|
|
|
/* vco 8640 */
|
|
|
|
|
switch (cdctl & CDCLK_FREQ_SEL_MASK) {
|
|
|
|
|
case CDCLK_FREQ_450_432:
|
|
|
|
|
return 432000;
|
|
|
|
|
case CDCLK_FREQ_337_308:
|
|
|
|
|
return 308570;
|
|
|
|
|
case CDCLK_FREQ_675_617:
|
|
|
|
|
return 617140;
|
|
|
|
|
default:
|
|
|
|
|
WARN(1, "Unknown cd freq selection\n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* vco 8100 */
|
|
|
|
|
switch (cdctl & CDCLK_FREQ_SEL_MASK) {
|
|
|
|
|
case CDCLK_FREQ_450_432:
|
|
|
|
|
return 450000;
|
|
|
|
|
case CDCLK_FREQ_337_308:
|
|
|
|
|
return 337500;
|
|
|
|
|
case CDCLK_FREQ_675_617:
|
|
|
|
|
return 675000;
|
|
|
|
|
default:
|
|
|
|
|
WARN(1, "Unknown cd freq selection\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* error case, do as if DPLL0 isn't enabled */
|
|
|
|
|
return 24000;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-23 14:14:26 -07:00
|
|
|
static int broxton_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
uint32_t cdctl = I915_READ(CDCLK_CTL);
|
|
|
|
|
uint32_t pll_ratio = I915_READ(BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
|
|
|
|
|
uint32_t pll_enab = I915_READ(BXT_DE_PLL_ENABLE);
|
|
|
|
|
int cdclk;
|
|
|
|
|
|
|
|
|
|
if (!(pll_enab & BXT_DE_PLL_PLL_ENABLE))
|
|
|
|
|
return 19200;
|
|
|
|
|
|
|
|
|
|
cdclk = 19200 * pll_ratio / 2;
|
|
|
|
|
|
|
|
|
|
switch (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) {
|
|
|
|
|
case BXT_CDCLK_CD2X_DIV_SEL_1:
|
|
|
|
|
return cdclk; /* 576MHz or 624MHz */
|
|
|
|
|
case BXT_CDCLK_CD2X_DIV_SEL_1_5:
|
|
|
|
|
return cdclk * 2 / 3; /* 384MHz */
|
|
|
|
|
case BXT_CDCLK_CD2X_DIV_SEL_2:
|
|
|
|
|
return cdclk / 2; /* 288MHz */
|
|
|
|
|
case BXT_CDCLK_CD2X_DIV_SEL_4:
|
|
|
|
|
return cdclk / 4; /* 144MHz */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* error case, do as if DE PLL isn't enabled */
|
|
|
|
|
return 19200;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 14:12:01 +03:00
|
|
|
static int broadwell_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t lcpll = I915_READ(LCPLL_CTL);
|
|
|
|
|
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
|
|
|
|
|
|
|
|
|
|
if (lcpll & LCPLL_CD_SOURCE_FCLK)
|
|
|
|
|
return 800000;
|
|
|
|
|
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
|
|
return 450000;
|
|
|
|
|
else if (freq == LCPLL_CLK_FREQ_450)
|
|
|
|
|
return 450000;
|
|
|
|
|
else if (freq == LCPLL_CLK_FREQ_54O_BDW)
|
|
|
|
|
return 540000;
|
|
|
|
|
else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
|
|
|
|
|
return 337500;
|
|
|
|
|
else
|
|
|
|
|
return 675000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int haswell_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t lcpll = I915_READ(LCPLL_CTL);
|
|
|
|
|
uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
|
|
|
|
|
|
|
|
|
|
if (lcpll & LCPLL_CD_SOURCE_FCLK)
|
|
|
|
|
return 800000;
|
|
|
|
|
else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
|
|
|
|
|
return 450000;
|
|
|
|
|
else if (freq == LCPLL_CLK_FREQ_450)
|
|
|
|
|
return 450000;
|
|
|
|
|
else if (IS_HSW_ULT(dev))
|
|
|
|
|
return 337500;
|
|
|
|
|
else
|
|
|
|
|
return 540000;
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2012-03-28 13:39:23 -07:00
|
|
|
static int valleyview_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
2015-09-24 23:29:18 +03:00
|
|
|
return vlv_get_cck_clock_hpll(to_i915(dev), "cdclk",
|
|
|
|
|
CCK_DISPLAY_CLOCK_CONTROL);
|
2012-03-28 13:39:23 -07:00
|
|
|
}
|
|
|
|
|
|
2015-03-31 14:11:54 +03:00
|
|
|
static int ilk_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
return 450000;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
{
|
2015-03-31 14:09:47 +03:00
|
|
|
return 333333;
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2013-07-26 08:35:42 +02:00
|
|
|
static int pnv_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
u16 gcfgc = 0;
|
|
|
|
|
|
|
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
|
|
|
|
|
|
|
|
|
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
|
|
|
|
|
case GC_DISPLAY_CLOCK_267_MHZ_PNV:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 266667;
|
2013-07-26 08:35:42 +02:00
|
|
|
case GC_DISPLAY_CLOCK_333_MHZ_PNV:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 333333;
|
2013-07-26 08:35:42 +02:00
|
|
|
case GC_DISPLAY_CLOCK_444_MHZ_PNV:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 444444;
|
2013-07-26 08:35:42 +02:00
|
|
|
case GC_DISPLAY_CLOCK_200_MHZ_PNV:
|
|
|
|
|
return 200000;
|
|
|
|
|
default:
|
|
|
|
|
DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
|
|
|
|
|
case GC_DISPLAY_CLOCK_133_MHZ_PNV:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 133333;
|
2013-07-26 08:35:42 +02:00
|
|
|
case GC_DISPLAY_CLOCK_167_MHZ_PNV:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 166667;
|
2013-07-26 08:35:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2009-09-21 10:42:27 -07:00
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
|
|
|
|
|
|
|
|
|
if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
|
2015-03-31 14:09:47 +03:00
|
|
|
return 133333;
|
2009-09-21 10:42:27 -07:00
|
|
|
else {
|
|
|
|
|
switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
|
|
|
|
|
case GC_DISPLAY_CLOCK_333_MHZ:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 333333;
|
2009-09-21 10:42:27 -07:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
2009-09-21 10:42:27 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int i865_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
2015-03-31 14:09:47 +03:00
|
|
|
return 266667;
|
2009-09-21 10:42:27 -07:00
|
|
|
}
|
|
|
|
|
|
2015-05-22 11:22:31 +03:00
|
|
|
static int i85x_get_display_clock_speed(struct drm_device *dev)
|
2009-09-21 10:42:27 -07:00
|
|
|
{
|
|
|
|
|
u16 hpllcc = 0;
|
2015-05-22 11:22:31 +03:00
|
|
|
|
2015-05-22 11:22:32 +03:00
|
|
|
/*
|
|
|
|
|
* 852GM/852GMV only supports 133 MHz and the HPLLCC
|
|
|
|
|
* encoding is different :(
|
|
|
|
|
* FIXME is this the right way to detect 852GM/852GMV?
|
|
|
|
|
*/
|
|
|
|
|
if (dev->pdev->revision == 0x1)
|
|
|
|
|
return 133333;
|
|
|
|
|
|
2015-05-22 11:22:31 +03:00
|
|
|
pci_bus_read_config_word(dev->pdev->bus,
|
|
|
|
|
PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
|
|
|
|
|
|
2009-09-21 10:42:27 -07:00
|
|
|
/* 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:
|
2015-05-22 11:22:31 +03:00
|
|
|
case GC_CLOCK_133_200_2:
|
2009-09-21 10:42:27 -07:00
|
|
|
case GC_CLOCK_100_200:
|
|
|
|
|
return 200000;
|
|
|
|
|
case GC_CLOCK_166_250:
|
|
|
|
|
return 250000;
|
|
|
|
|
case GC_CLOCK_100_133:
|
2015-03-31 14:09:47 +03:00
|
|
|
return 133333;
|
2015-05-22 11:22:31 +03:00
|
|
|
case GC_CLOCK_133_266:
|
|
|
|
|
case GC_CLOCK_133_266_2:
|
|
|
|
|
case GC_CLOCK_166_266:
|
|
|
|
|
return 266667;
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2009-09-21 10:42:27 -07: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-07 14:24:08 -08:00
|
|
|
|
2009-09-21 10:42:27 -07:00
|
|
|
static int i830_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
2015-03-31 14:09:47 +03:00
|
|
|
return 133333;
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-05-22 11:22:33 +03:00
|
|
|
static unsigned int intel_hpll_vco(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
static const unsigned int blb_vco[8] = {
|
|
|
|
|
[0] = 3200000,
|
|
|
|
|
[1] = 4000000,
|
|
|
|
|
[2] = 5333333,
|
|
|
|
|
[3] = 4800000,
|
|
|
|
|
[4] = 6400000,
|
|
|
|
|
};
|
|
|
|
|
static const unsigned int pnv_vco[8] = {
|
|
|
|
|
[0] = 3200000,
|
|
|
|
|
[1] = 4000000,
|
|
|
|
|
[2] = 5333333,
|
|
|
|
|
[3] = 4800000,
|
|
|
|
|
[4] = 2666667,
|
|
|
|
|
};
|
|
|
|
|
static const unsigned int cl_vco[8] = {
|
|
|
|
|
[0] = 3200000,
|
|
|
|
|
[1] = 4000000,
|
|
|
|
|
[2] = 5333333,
|
|
|
|
|
[3] = 6400000,
|
|
|
|
|
[4] = 3333333,
|
|
|
|
|
[5] = 3566667,
|
|
|
|
|
[6] = 4266667,
|
|
|
|
|
};
|
|
|
|
|
static const unsigned int elk_vco[8] = {
|
|
|
|
|
[0] = 3200000,
|
|
|
|
|
[1] = 4000000,
|
|
|
|
|
[2] = 5333333,
|
|
|
|
|
[3] = 4800000,
|
|
|
|
|
};
|
|
|
|
|
static const unsigned int ctg_vco[8] = {
|
|
|
|
|
[0] = 3200000,
|
|
|
|
|
[1] = 4000000,
|
|
|
|
|
[2] = 5333333,
|
|
|
|
|
[3] = 6400000,
|
|
|
|
|
[4] = 2666667,
|
|
|
|
|
[5] = 4266667,
|
|
|
|
|
};
|
|
|
|
|
const unsigned int *vco_table;
|
|
|
|
|
unsigned int vco;
|
|
|
|
|
uint8_t tmp = 0;
|
|
|
|
|
|
|
|
|
|
/* FIXME other chipsets? */
|
|
|
|
|
if (IS_GM45(dev))
|
|
|
|
|
vco_table = ctg_vco;
|
|
|
|
|
else if (IS_G4X(dev))
|
|
|
|
|
vco_table = elk_vco;
|
|
|
|
|
else if (IS_CRESTLINE(dev))
|
|
|
|
|
vco_table = cl_vco;
|
|
|
|
|
else if (IS_PINEVIEW(dev))
|
|
|
|
|
vco_table = pnv_vco;
|
|
|
|
|
else if (IS_G33(dev))
|
|
|
|
|
vco_table = blb_vco;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
tmp = I915_READ(IS_MOBILE(dev) ? HPLLVCO_MOBILE : HPLLVCO);
|
|
|
|
|
|
|
|
|
|
vco = vco_table[tmp & 0x7];
|
|
|
|
|
if (vco == 0)
|
|
|
|
|
DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
|
|
|
|
|
else
|
|
|
|
|
DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
|
|
|
|
|
|
|
|
|
|
return vco;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int gm45_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
|
|
|
|
|
uint16_t tmp = 0;
|
|
|
|
|
|
|
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &tmp);
|
|
|
|
|
|
|
|
|
|
cdclk_sel = (tmp >> 12) & 0x1;
|
|
|
|
|
|
|
|
|
|
switch (vco) {
|
|
|
|
|
case 2666667:
|
|
|
|
|
case 4000000:
|
|
|
|
|
case 5333333:
|
|
|
|
|
return cdclk_sel ? 333333 : 222222;
|
|
|
|
|
case 3200000:
|
|
|
|
|
return cdclk_sel ? 320000 : 228571;
|
|
|
|
|
default:
|
|
|
|
|
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n", vco, tmp);
|
|
|
|
|
return 222222;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int i965gm_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
static const uint8_t div_3200[] = { 16, 10, 8 };
|
|
|
|
|
static const uint8_t div_4000[] = { 20, 12, 10 };
|
|
|
|
|
static const uint8_t div_5333[] = { 24, 16, 14 };
|
|
|
|
|
const uint8_t *div_table;
|
|
|
|
|
unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
|
|
|
|
|
uint16_t tmp = 0;
|
|
|
|
|
|
|
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &tmp);
|
|
|
|
|
|
|
|
|
|
cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
|
|
|
|
|
|
|
|
|
|
if (cdclk_sel >= ARRAY_SIZE(div_3200))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
switch (vco) {
|
|
|
|
|
case 3200000:
|
|
|
|
|
div_table = div_3200;
|
|
|
|
|
break;
|
|
|
|
|
case 4000000:
|
|
|
|
|
div_table = div_4000;
|
|
|
|
|
break;
|
|
|
|
|
case 5333333:
|
|
|
|
|
div_table = div_5333;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
|
|
|
|
|
|
2015-06-04 16:56:18 +01:00
|
|
|
fail:
|
2015-05-22 11:22:33 +03:00
|
|
|
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n", vco, tmp);
|
|
|
|
|
return 200000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int g33_get_display_clock_speed(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 };
|
|
|
|
|
static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 };
|
|
|
|
|
static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
|
|
|
|
|
static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
|
|
|
|
|
const uint8_t *div_table;
|
|
|
|
|
unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
|
|
|
|
|
uint16_t tmp = 0;
|
|
|
|
|
|
|
|
|
|
pci_read_config_word(dev->pdev, GCFGC, &tmp);
|
|
|
|
|
|
|
|
|
|
cdclk_sel = (tmp >> 4) & 0x7;
|
|
|
|
|
|
|
|
|
|
if (cdclk_sel >= ARRAY_SIZE(div_3200))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
switch (vco) {
|
|
|
|
|
case 3200000:
|
|
|
|
|
div_table = div_3200;
|
|
|
|
|
break;
|
|
|
|
|
case 4000000:
|
|
|
|
|
div_table = div_4000;
|
|
|
|
|
break;
|
|
|
|
|
case 4800000:
|
|
|
|
|
div_table = div_4800;
|
|
|
|
|
break;
|
|
|
|
|
case 5333333:
|
|
|
|
|
div_table = div_5333;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DIV_ROUND_CLOSEST(vco, div_table[cdclk_sel]);
|
|
|
|
|
|
2015-06-04 16:56:18 +01:00
|
|
|
fail:
|
2015-05-22 11:22:33 +03:00
|
|
|
DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n", vco, tmp);
|
|
|
|
|
return 190476;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-05 15:38:42 +08:00
|
|
|
static void
|
2013-04-23 15:03:34 +03:00
|
|
|
intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
|
2009-06-05 15:38:42 +08:00
|
|
|
{
|
2013-04-23 15:03:34 +03: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 15:03:34 +03: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 15:59:36 +01: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 15:59:36 +01:00
|
|
|
m_n->tu = 64;
|
2013-04-23 15:03:34 +03: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-12 17:04:08 +00:00
|
|
|
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
2014-01-21 11:24:25 +02:00
|
|
|
if (i915.panel_use_ssc >= 0)
|
|
|
|
|
return i915.panel_use_ssc != 0;
|
2013-05-09 20:03:18 -03:00
|
|
|
return dev_priv->vbt.lvds_use_ssc
|
2011-07-12 14:56:22 -07:00
|
|
|
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
|
2011-01-12 17:04:08 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
|
|
|
|
|
int num_connectors)
|
2011-12-15 12:30:36 -08:00
|
|
|
{
|
2015-03-20 16:18:17 +02:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
2011-12-15 12:30:36 -08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int refclk;
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
WARN_ON(!crtc_state->base.state);
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
|
2013-09-16 11:29:34 +02:00
|
|
|
refclk = 100000;
|
2015-03-20 16:18:17 +02:00
|
|
|
} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
2011-12-15 12:30:36 -08:00
|
|
|
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
2013-12-09 18:54:16 +02:00
|
|
|
refclk = dev_priv->vbt.lvds_ssc_freq;
|
|
|
|
|
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
|
2011-12-15 12:30:36 -08:00
|
|
|
} else if (!IS_GEN2(dev)) {
|
|
|
|
|
refclk = 96000;
|
|
|
|
|
} else {
|
|
|
|
|
refclk = 48000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return refclk;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-20 17:19:46 +02:00
|
|
|
static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
|
2011-12-15 12:30:36 -08:00
|
|
|
{
|
2013-05-21 21:54:55 +02:00
|
|
|
return (1 << dpll->n) << 16 | dpll->m2;
|
2013-04-20 17:19:46 +02:00
|
|
|
}
|
2013-03-28 10:42:02 +01:00
|
|
|
|
2013-04-20 17:19:46 +02:00
|
|
|
static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
|
|
|
|
|
{
|
|
|
|
|
return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
|
2011-12-15 12:30:36 -08:00
|
|
|
}
|
|
|
|
|
|
2013-03-28 10:42:02 +01:00
|
|
|
static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
|
2015-01-15 14:55:23 +02:00
|
|
|
struct intel_crtc_state *crtc_state,
|
2011-12-15 12:30:37 -08:00
|
|
|
intel_clock_t *reduced_clock)
|
|
|
|
|
{
|
2013-03-28 10:42:02 +01:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2011-12-15 12:30:37 -08:00
|
|
|
u32 fp, fp2 = 0;
|
|
|
|
|
|
|
|
|
|
if (IS_PINEVIEW(dev)) {
|
2015-01-15 14:55:23 +02:00
|
|
|
fp = pnv_dpll_compute_fp(&crtc_state->dpll);
|
2011-12-15 12:30:37 -08:00
|
|
|
if (reduced_clock)
|
2013-04-20 17:19:46 +02:00
|
|
|
fp2 = pnv_dpll_compute_fp(reduced_clock);
|
2011-12-15 12:30:37 -08:00
|
|
|
} else {
|
2015-01-15 14:55:23 +02:00
|
|
|
fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
|
2011-12-15 12:30:37 -08:00
|
|
|
if (reduced_clock)
|
2013-04-20 17:19:46 +02:00
|
|
|
fp2 = i9xx_dpll_compute_fp(reduced_clock);
|
2011-12-15 12:30:37 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.fp0 = fp;
|
2011-12-15 12:30:37 -08:00
|
|
|
|
2013-03-28 10:42:02 +01:00
|
|
|
crtc->lowfreq_avail = false;
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
2015-03-24 12:40:09 -07:00
|
|
|
reduced_clock) {
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.fp1 = fp2;
|
2013-03-28 10:42:02 +01:00
|
|
|
crtc->lowfreq_avail = true;
|
2011-12-15 12:30:37 -08:00
|
|
|
} else {
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.fp1 = fp;
|
2011-12-15 12:30:37 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-05 20:41:49 +08:00
|
|
|
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
|
|
|
|
|
pipe)
|
2013-04-18 14:51:36 -07:00
|
|
|
{
|
|
|
|
|
u32 reg_val;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* PLLB opamp always calibrates to max value of 0x3f, force enable it
|
|
|
|
|
* and set it to a reasonable value instead.
|
|
|
|
|
*/
|
2013-11-07 10:43:30 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
2013-04-18 14:51:36 -07:00
|
|
|
reg_val &= 0xffffff00;
|
|
|
|
|
reg_val |= 0x00000030;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
2013-11-07 10:43:30 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
2013-04-18 14:51:36 -07:00
|
|
|
reg_val &= 0x8cffffff;
|
|
|
|
|
reg_val = 0x8c000000;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
2013-11-07 10:43:30 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
|
2013-04-18 14:51:36 -07:00
|
|
|
reg_val &= 0xffffff00;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
2013-11-07 10:43:30 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
|
2013-04-18 14:51:36 -07:00
|
|
|
reg_val &= 0x00ffffff;
|
|
|
|
|
reg_val |= 0xb0000000;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
|
2013-04-18 14:51:36 -07:00
|
|
|
}
|
|
|
|
|
|
2013-05-03 11:49:48 +02: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 11:49:49 +02: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 11:49:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
|
2014-08-05 07:51:22 -07:00
|
|
|
struct intel_link_m_n *m_n,
|
|
|
|
|
struct intel_link_m_n *m2_n2)
|
2013-05-03 11:49:48 +02:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = crtc->pipe;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder transcoder = crtc->config->cpu_transcoder;
|
2013-05-03 11:49:48 +02:00
|
|
|
|
|
|
|
|
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);
|
2014-08-05 07:51:22 -07:00
|
|
|
/* M2_N2 registers to be set only for gen < 8 (M2_N2 available
|
|
|
|
|
* for gen < 8) and if DRRS is supported (to make sure the
|
|
|
|
|
* registers are not unnecessarily accessed).
|
|
|
|
|
*/
|
2015-02-13 15:33:02 +05:30
|
|
|
if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
|
2015-01-15 14:55:25 +02:00
|
|
|
crtc->config->has_drrs) {
|
2014-08-05 07:51:22 -07:00
|
|
|
I915_WRITE(PIPE_DATA_M2(transcoder),
|
|
|
|
|
TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
|
|
|
|
|
I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
|
|
|
|
|
I915_WRITE(PIPE_LINK_M2(transcoder), m2_n2->link_m);
|
|
|
|
|
I915_WRITE(PIPE_LINK_N2(transcoder), m2_n2->link_n);
|
|
|
|
|
}
|
2013-05-03 11:49:48 +02:00
|
|
|
} else {
|
2013-05-03 11:49:49 +02: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 11:49:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 15:32:59 +05:30
|
|
|
void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
|
2013-04-02 23:42:31 +02:00
|
|
|
{
|
2015-02-13 15:32:59 +05:30
|
|
|
struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
|
|
|
|
|
|
|
|
|
|
if (m_n == M1_N1) {
|
|
|
|
|
dp_m_n = &crtc->config->dp_m_n;
|
|
|
|
|
dp_m2_n2 = &crtc->config->dp_m2_n2;
|
|
|
|
|
} else if (m_n == M2_N2) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* M2_N2 registers are not supported. Hence m2_n2 divider value
|
|
|
|
|
* needs to be programmed into M1_N1.
|
|
|
|
|
*/
|
|
|
|
|
dp_m_n = &crtc->config->dp_m2_n2;
|
|
|
|
|
} else {
|
|
|
|
|
DRM_ERROR("Unsupported divider value\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (crtc->config->has_pch_encoder)
|
|
|
|
|
intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
|
2013-04-02 23:42:31 +02:00
|
|
|
else
|
2015-02-13 15:32:59 +05:30
|
|
|
intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
|
2013-04-02 23:42:31 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-18 10:30:24 +02:00
|
|
|
static void vlv_compute_dpll(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-04-24 23:55:11 +02:00
|
|
|
{
|
|
|
|
|
u32 dpll, dpll_md;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Enable DPIO clock input. We should never disable the reference
|
|
|
|
|
* clock for pipe B, since VGA hotplug / manual detection depends
|
|
|
|
|
* on it.
|
|
|
|
|
*/
|
2015-06-29 15:25:49 +03:00
|
|
|
dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REF_CLK_ENABLE_VLV |
|
|
|
|
|
DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_REF_CLK_VLV;
|
2014-04-24 23:55:11 +02:00
|
|
|
/* We should never disable this, set it here for state tracking */
|
|
|
|
|
if (crtc->pipe == PIPE_B)
|
|
|
|
|
dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
|
|
|
|
dpll |= DPLL_VCO_ENABLE;
|
2014-10-28 13:20:22 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll = dpll;
|
2014-04-24 23:55:11 +02:00
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
dpll_md = (pipe_config->pixel_multiplier - 1)
|
2014-04-24 23:55:11 +02:00
|
|
|
<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
|
2014-10-28 13:20:22 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll_md = dpll_md;
|
2014-04-24 23:55:11 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
static void vlv_prepare_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config)
|
2012-06-15 11:55:13 -07:00
|
|
|
{
|
2013-03-28 10:42:02 +01:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-06-15 11:55:13 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-03-28 10:42:02 +01:00
|
|
|
int pipe = crtc->pipe;
|
2014-04-24 23:55:11 +02:00
|
|
|
u32 mdiv;
|
2012-06-15 11:55:13 -07:00
|
|
|
u32 bestn, bestm1, bestm2, bestp1, bestp2;
|
2014-04-24 23:55:11 +02:00
|
|
|
u32 coreclk, reg_val;
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2012-12-12 14:06:44 +01:00
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
bestn = pipe_config->dpll.n;
|
|
|
|
|
bestm1 = pipe_config->dpll.m1;
|
|
|
|
|
bestm2 = pipe_config->dpll.m2;
|
|
|
|
|
bestp1 = pipe_config->dpll.p1;
|
|
|
|
|
bestp2 = pipe_config->dpll.p2;
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
/* See eDP HDMI DPIO driver vbios notes doc */
|
|
|
|
|
|
|
|
|
|
/* PLL B needs special handling */
|
2014-04-24 23:55:11 +02:00
|
|
|
if (pipe == PIPE_B)
|
2013-09-05 20:41:49 +08:00
|
|
|
vlv_pllb_recal_opamp(dev_priv, pipe);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
|
|
|
|
/* Set up Tx target for periodic Rcomp update */
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
|
|
|
|
/* Disable target IRef on PLL */
|
2013-11-07 10:43:30 +08:00
|
|
|
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
|
2013-04-18 14:51:36 -07:00
|
|
|
reg_val &= 0x00ffffff;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
|
|
|
|
/* Disable fast lock */
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
|
2013-04-18 14:51:36 -07:00
|
|
|
|
|
|
|
|
/* Set idtafcrecal before PLL is enabled */
|
2012-06-15 11:55:13 -07: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-02 10:48:09 -07: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-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
2012-06-15 11:55:13 -07:00
|
|
|
|
|
|
|
|
mdiv |= DPIO_ENABLE_CALIBRATION;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2013-04-18 14:51:36 -07:00
|
|
|
/* Set HBR and RBR LPF coefficients */
|
2014-10-28 13:20:22 +02:00
|
|
|
if (pipe_config->port_clock == 162000 ||
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG) ||
|
|
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
2013-07-05 19:21:38 +03:00
|
|
|
0x009f0003);
|
2013-04-18 14:51:36 -07:00
|
|
|
else
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
|
2013-04-18 14:51:36 -07:00
|
|
|
0x00d0000f);
|
|
|
|
|
|
2015-01-15 14:55:24 +02:00
|
|
|
if (pipe_config->has_dp_encoder) {
|
2013-04-18 14:51:36 -07:00
|
|
|
/* Use SSC source */
|
2014-04-24 23:55:11 +02:00
|
|
|
if (pipe == PIPE_A)
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
2013-04-18 14:51:36 -07:00
|
|
|
0x0df40000);
|
|
|
|
|
else
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
2013-04-18 14:51:36 -07:00
|
|
|
0x0df70000);
|
|
|
|
|
} else { /* HDMI or VGA */
|
|
|
|
|
/* Use bend source */
|
2014-04-24 23:55:11 +02:00
|
|
|
if (pipe == PIPE_A)
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
2013-04-18 14:51:36 -07:00
|
|
|
0x0df70000);
|
|
|
|
|
else
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
|
2013-04-18 14:51:36 -07:00
|
|
|
0x0df40000);
|
|
|
|
|
}
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2013-11-07 10:43:30 +08:00
|
|
|
coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
|
2013-04-18 14:51:36 -07:00
|
|
|
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
|
2014-10-20 13:46:45 +03:00
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
|
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
|
2013-04-18 14:51:36 -07:00
|
|
|
coreclk |= 0x01000000;
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
|
2012-06-15 11:55:13 -07:00
|
|
|
|
2013-11-07 10:43:30 +08:00
|
|
|
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2012-06-15 11:55:13 -07:00
|
|
|
}
|
|
|
|
|
|
2015-06-18 10:30:24 +02:00
|
|
|
static void chv_compute_dpll(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-06-28 02:04:00 +03:00
|
|
|
{
|
2015-06-29 15:25:49 +03:00
|
|
|
pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
|
|
|
|
|
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
|
2014-06-28 02:04:00 +03:00
|
|
|
DPLL_VCO_ENABLE;
|
|
|
|
|
if (crtc->pipe != PIPE_A)
|
2014-10-28 13:20:22 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
|
2014-06-28 02:04:00 +03:00
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll_md =
|
|
|
|
|
(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
|
2014-06-28 02:04:00 +03:00
|
|
|
}
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
static void chv_prepare_pll(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config)
|
2014-05-02 14:27:47 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = crtc->pipe;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t dpll_reg = DPLL(crtc->pipe);
|
2014-05-02 14:27:47 +03:00
|
|
|
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
2015-03-05 19:33:08 +05:30
|
|
|
u32 loopfilter, tribuf_calcntr;
|
2014-05-02 14:27:47 +03:00
|
|
|
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
|
2015-03-05 19:30:57 +05:30
|
|
|
u32 dpio_val;
|
2015-03-05 19:33:08 +05:30
|
|
|
int vco;
|
2014-05-02 14:27:47 +03:00
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
bestn = pipe_config->dpll.n;
|
|
|
|
|
bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
|
|
|
|
|
bestm1 = pipe_config->dpll.m1;
|
|
|
|
|
bestm2 = pipe_config->dpll.m2 >> 22;
|
|
|
|
|
bestp1 = pipe_config->dpll.p1;
|
|
|
|
|
bestp2 = pipe_config->dpll.p2;
|
2015-03-05 19:33:08 +05:30
|
|
|
vco = pipe_config->dpll.vco;
|
2015-03-05 19:30:57 +05:30
|
|
|
dpio_val = 0;
|
2015-03-05 19:33:08 +05:30
|
|
|
loopfilter = 0;
|
2014-05-02 14:27:47 +03:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Enable Refclk and SSC
|
|
|
|
|
*/
|
2014-04-09 13:28:57 +03:00
|
|
|
I915_WRITE(dpll_reg,
|
2014-10-28 13:20:22 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
|
2014-04-09 13:28:57 +03:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2014-05-02 14:27:47 +03:00
|
|
|
|
|
|
|
|
/* p1 and p2 divider */
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
|
|
|
|
|
5 << DPIO_CHV_S1_DIV_SHIFT |
|
|
|
|
|
bestp1 << DPIO_CHV_P1_DIV_SHIFT |
|
|
|
|
|
bestp2 << DPIO_CHV_P2_DIV_SHIFT |
|
|
|
|
|
1 << DPIO_CHV_K_DIV_SHIFT);
|
|
|
|
|
|
|
|
|
|
/* Feedback post-divider - m2 */
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW0(port), bestm2);
|
|
|
|
|
|
|
|
|
|
/* Feedback refclk divider - n and m1 */
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW1(port),
|
|
|
|
|
DPIO_CHV_M1_DIV_BY_2 |
|
|
|
|
|
1 << DPIO_CHV_N_DIV_SHIFT);
|
|
|
|
|
|
|
|
|
|
/* M2 fraction division */
|
2015-07-08 23:45:47 +03:00
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
|
2014-05-02 14:27:47 +03:00
|
|
|
|
|
|
|
|
/* M2 fraction division enable */
|
2015-03-05 19:30:57 +05:30
|
|
|
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
|
|
|
|
|
dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
|
|
|
|
|
dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT);
|
|
|
|
|
if (bestm2_frac)
|
|
|
|
|
dpio_val |= DPIO_CHV_FRAC_DIV_EN;
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val);
|
2014-05-02 14:27:47 +03:00
|
|
|
|
2015-03-05 19:32:06 +05:30
|
|
|
/* Program digital lock detect threshold */
|
|
|
|
|
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port));
|
|
|
|
|
dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
|
|
|
|
|
DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
|
|
|
|
|
dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT);
|
|
|
|
|
if (!bestm2_frac)
|
|
|
|
|
dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val);
|
|
|
|
|
|
2014-05-02 14:27:47 +03:00
|
|
|
/* Loop filter */
|
2015-03-05 19:33:08 +05:30
|
|
|
if (vco == 5400000) {
|
|
|
|
|
loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
|
|
|
|
tribuf_calcntr = 0x9;
|
|
|
|
|
} else if (vco <= 6200000) {
|
|
|
|
|
loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
|
|
|
|
tribuf_calcntr = 0x9;
|
|
|
|
|
} else if (vco <= 6480000) {
|
|
|
|
|
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
|
|
|
|
tribuf_calcntr = 0x8;
|
|
|
|
|
} else {
|
|
|
|
|
/* Not supported. Apply the same limits as in the max case */
|
|
|
|
|
loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
|
|
|
|
|
loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
|
|
|
|
|
tribuf_calcntr = 0;
|
|
|
|
|
}
|
2014-05-02 14:27:47 +03:00
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
|
|
|
|
|
|
2015-03-11 22:52:08 +02:00
|
|
|
dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port));
|
2015-03-05 19:33:08 +05:30
|
|
|
dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
|
|
|
|
|
dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT);
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val);
|
|
|
|
|
|
2014-05-02 14:27:47 +03:00
|
|
|
/* AFC Recal */
|
|
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port),
|
|
|
|
|
vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
|
|
|
|
|
DPIO_AFC_RECAL);
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2014-05-02 14:27:47 +03:00
|
|
|
}
|
|
|
|
|
|
2014-10-28 13:20:22 +02:00
|
|
|
/**
|
|
|
|
|
* vlv_force_pll_on - forcibly enable just the PLL
|
|
|
|
|
* @dev_priv: i915 private structure
|
|
|
|
|
* @pipe: pipe PLL to enable
|
|
|
|
|
* @dpll: PLL configuration
|
|
|
|
|
*
|
|
|
|
|
* Enable the PLL for @pipe using the supplied @dpll config. To be used
|
|
|
|
|
* in cases where we need the PLL enabled even when @pipe is not going to
|
|
|
|
|
* be enabled.
|
|
|
|
|
*/
|
|
|
|
|
void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
|
|
|
|
|
const struct dpll *dpll)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *crtc =
|
|
|
|
|
to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state pipe_config = {
|
2015-03-20 16:18:17 +02:00
|
|
|
.base.crtc = &crtc->base,
|
2014-10-28 13:20:22 +02:00
|
|
|
.pixel_multiplier = 1,
|
|
|
|
|
.dpll = *dpll,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
2015-06-18 10:30:24 +02:00
|
|
|
chv_compute_dpll(crtc, &pipe_config);
|
2014-10-28 13:20:22 +02:00
|
|
|
chv_prepare_pll(crtc, &pipe_config);
|
|
|
|
|
chv_enable_pll(crtc, &pipe_config);
|
|
|
|
|
} else {
|
2015-06-18 10:30:24 +02:00
|
|
|
vlv_compute_dpll(crtc, &pipe_config);
|
2014-10-28 13:20:22 +02:00
|
|
|
vlv_prepare_pll(crtc, &pipe_config);
|
|
|
|
|
vlv_enable_pll(crtc, &pipe_config);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* vlv_force_pll_off - forcibly disable just the PLL
|
|
|
|
|
* @dev_priv: i915 private structure
|
|
|
|
|
* @pipe: pipe PLL to disable
|
|
|
|
|
*
|
|
|
|
|
* Disable the PLL for @pipe. To be used in cases where we need
|
|
|
|
|
* the PLL enabled even when @pipe is not going to be enabled.
|
|
|
|
|
*/
|
|
|
|
|
void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
|
|
|
|
|
{
|
|
|
|
|
if (IS_CHERRYVIEW(dev))
|
|
|
|
|
chv_disable_pll(to_i915(dev), pipe);
|
|
|
|
|
else
|
|
|
|
|
vlv_disable_pll(to_i915(dev), pipe);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 10:30:24 +02:00
|
|
|
static void i9xx_compute_dpll(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
|
|
|
|
intel_clock_t *reduced_clock,
|
|
|
|
|
int num_connectors)
|
2012-03-28 23:12:16 +02:00
|
|
|
{
|
2013-03-28 10:42:02 +01:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-03-28 23:12:16 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 dpll;
|
|
|
|
|
bool is_sdvo;
|
2015-01-15 14:55:23 +02:00
|
|
|
struct dpll *clock = &crtc_state->dpll;
|
2012-03-28 23:12:16 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
|
2012-09-27 19:13:06 +05:30
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
is_sdvo = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO) ||
|
|
|
|
|
intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI);
|
2012-03-28 23:12:16 +02:00
|
|
|
|
|
|
|
|
dpll = DPLL_VGA_MODE_DIS;
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
|
2012-03-28 23:12:16 +02:00
|
|
|
dpll |= DPLLB_MODE_LVDS;
|
|
|
|
|
else
|
|
|
|
|
dpll |= DPLLB_MODE_DAC_SERIAL;
|
2013-03-27 00:44:53 +01:00
|
|
|
|
2013-06-01 17:17:04 +02:00
|
|
|
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
|
2015-01-15 14:55:23 +02:00
|
|
|
dpll |= (crtc_state->pixel_multiplier - 1)
|
2013-04-19 11:14:37 +02:00
|
|
|
<< SDVO_MULTIPLIER_SHIFT_HIRES;
|
2012-03-28 23:12:16 +02:00
|
|
|
}
|
2013-04-19 11:14:37 +02:00
|
|
|
|
|
|
|
|
if (is_sdvo)
|
2013-07-06 12:52:05 +02:00
|
|
|
dpll |= DPLL_SDVO_HIGH_SPEED;
|
2013-04-19 11:14:37 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
if (crtc_state->has_dp_encoder)
|
2013-07-06 12:52:05 +02:00
|
|
|
dpll |= DPLL_SDVO_HIGH_SPEED;
|
2012-03-28 23:12:16 +02:00
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
if (crtc_state->sdvo_tv_clock)
|
2012-03-28 23:12:16 +02:00
|
|
|
dpll |= PLL_REF_INPUT_TVCLKINBC;
|
2015-03-20 16:18:17 +02:00
|
|
|
else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
2012-03-28 23:12:16 +02: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;
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.dpll = dpll;
|
2013-06-05 13:34:28 +02:00
|
|
|
|
2012-03-28 23:12:16 +02:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2015-01-15 14:55:23 +02:00
|
|
|
u32 dpll_md = (crtc_state->pixel_multiplier - 1)
|
2013-06-01 17:17:04 +02:00
|
|
|
<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.dpll_md = dpll_md;
|
2012-03-28 23:12:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 10:30:24 +02:00
|
|
|
static void i8xx_compute_dpll(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state,
|
|
|
|
|
intel_clock_t *reduced_clock,
|
|
|
|
|
int num_connectors)
|
2012-03-28 23:12:16 +02:00
|
|
|
{
|
2013-03-28 10:42:02 +01:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-03-28 23:12:16 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 dpll;
|
2015-01-15 14:55:23 +02:00
|
|
|
struct dpll *clock = &crtc_state->dpll;
|
2012-03-28 23:12:16 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
i9xx_update_pll_dividers(crtc, crtc_state, reduced_clock);
|
2012-09-27 19:13:06 +05:30
|
|
|
|
2012-03-28 23:12:16 +02:00
|
|
|
dpll = DPLL_VGA_MODE_DIS;
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
|
2012-03-28 23:12:16 +02: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (!IS_I830(dev) && intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO))
|
2013-07-06 12:52:05 +02:00
|
|
|
dpll |= DPLL_DVO_2X_MODE;
|
|
|
|
|
|
2015-03-20 16:18:17 +02:00
|
|
|
if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
2012-03-28 23:12:16 +02: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;
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.dpll = dpll;
|
2012-03-28 23:12:16 +02:00
|
|
|
}
|
|
|
|
|
|
2013-06-01 17:16:22 +02:00
|
|
|
static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
|
2012-10-01 18:10:53 -03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
2015-09-08 13:40:49 +03:00
|
|
|
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
|
2014-03-28 23:29:32 +02:00
|
|
|
uint32_t crtc_vtotal, crtc_vblank_end;
|
|
|
|
|
int vsyncshift = 0;
|
2013-05-03 11:49:51 +02:00
|
|
|
|
|
|
|
|
/* 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-01 18:10:53 -03:00
|
|
|
|
2014-03-28 23:29:30 +02:00
|
|
|
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
|
2012-10-01 18:10:53 -03:00
|
|
|
/* the chip adds 2 halflines automatically */
|
2013-05-03 11:49:51 +02:00
|
|
|
crtc_vtotal -= 1;
|
|
|
|
|
crtc_vblank_end -= 1;
|
2014-03-28 23:29:30 +02:00
|
|
|
|
2014-10-20 13:46:45 +03:00
|
|
|
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
|
2014-03-28 23:29:30 +02:00
|
|
|
vsyncshift = (adjusted_mode->crtc_htotal - 1) / 2;
|
|
|
|
|
else
|
|
|
|
|
vsyncshift = adjusted_mode->crtc_hsync_start -
|
|
|
|
|
adjusted_mode->crtc_htotal / 2;
|
2014-03-28 23:29:32 +02:00
|
|
|
if (vsyncshift < 0)
|
|
|
|
|
vsyncshift += adjusted_mode->crtc_htotal;
|
2012-10-01 18:10:53 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen > 3)
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift);
|
2012-10-01 18:10:53 -03:00
|
|
|
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(HTOTAL(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_hdisplay - 1) |
|
|
|
|
|
((adjusted_mode->crtc_htotal - 1) << 16));
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(HBLANK(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_hblank_start - 1) |
|
|
|
|
|
((adjusted_mode->crtc_hblank_end - 1) << 16));
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(HSYNC(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_hsync_start - 1) |
|
|
|
|
|
((adjusted_mode->crtc_hsync_end - 1) << 16));
|
|
|
|
|
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(VTOTAL(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_vdisplay - 1) |
|
2013-05-03 11:49:51 +02:00
|
|
|
((crtc_vtotal - 1) << 16));
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(VBLANK(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_vblank_start - 1) |
|
2013-05-03 11:49:51 +02:00
|
|
|
((crtc_vblank_end - 1) << 16));
|
2012-10-23 18:30:02 -02:00
|
|
|
I915_WRITE(VSYNC(cpu_transcoder),
|
2012-10-01 18:10:53 -03:00
|
|
|
(adjusted_mode->crtc_vsync_start - 1) |
|
|
|
|
|
((adjusted_mode->crtc_vsync_end - 1) << 16));
|
|
|
|
|
|
2012-10-24 11:34:43 -02: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-01 18:10:53 -03:00
|
|
|
/* pipesrc controls the size that is scaled from, which should
|
|
|
|
|
* always be the user's requested size.
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(PIPESRC(pipe),
|
2015-01-15 14:55:25 +02:00
|
|
|
((intel_crtc->config->pipe_src_w - 1) << 16) |
|
|
|
|
|
(intel_crtc->config->pipe_src_h - 1));
|
2012-10-01 18:10:53 -03:00
|
|
|
}
|
|
|
|
|
|
2013-04-29 21:56:12 +02:00
|
|
|
static void intel_get_pipe_timings(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-04-29 21:56:12 +02:00
|
|
|
{
|
|
|
|
|
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));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
tmp = I915_READ(HBLANK(cpu_transcoder));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
tmp = I915_READ(HSYNC(cpu_transcoder));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
|
|
|
|
|
tmp = I915_READ(VTOTAL(cpu_transcoder));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
tmp = I915_READ(VBLANK(cpu_transcoder));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
tmp = I915_READ(VSYNC(cpu_transcoder));
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
|
|
|
|
|
if (I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK) {
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_vtotal += 1;
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_vblank_end += 1;
|
2013-04-29 21:56:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp = I915_READ(PIPESRC(crtc->pipe));
|
2013-09-04 18:25:28 +03:00
|
|
|
pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
|
|
|
|
|
pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1;
|
|
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.mode.vdisplay = pipe_config->pipe_src_h;
|
|
|
|
|
pipe_config->base.mode.hdisplay = pipe_config->pipe_src_w;
|
2013-04-29 21:56:12 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-11 15:28:57 -08:00
|
|
|
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-06-26 18:57:38 +03:00
|
|
|
{
|
2015-01-15 14:55:22 +02:00
|
|
|
mode->hdisplay = pipe_config->base.adjusted_mode.crtc_hdisplay;
|
|
|
|
|
mode->htotal = pipe_config->base.adjusted_mode.crtc_htotal;
|
|
|
|
|
mode->hsync_start = pipe_config->base.adjusted_mode.crtc_hsync_start;
|
|
|
|
|
mode->hsync_end = pipe_config->base.adjusted_mode.crtc_hsync_end;
|
2013-06-26 18:57:38 +03:00
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
mode->vdisplay = pipe_config->base.adjusted_mode.crtc_vdisplay;
|
|
|
|
|
mode->vtotal = pipe_config->base.adjusted_mode.crtc_vtotal;
|
|
|
|
|
mode->vsync_start = pipe_config->base.adjusted_mode.crtc_vsync_start;
|
|
|
|
|
mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end;
|
2013-06-26 18:57:38 +03:00
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
mode->flags = pipe_config->base.adjusted_mode.flags;
|
2015-07-14 14:12:02 +02:00
|
|
|
mode->type = DRM_MODE_TYPE_DRIVER;
|
2013-06-26 18:57:38 +03:00
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
mode->clock = pipe_config->base.adjusted_mode.crtc_clock;
|
|
|
|
|
mode->flags |= pipe_config->base.adjusted_mode.flags;
|
2015-07-14 14:12:02 +02:00
|
|
|
|
|
|
|
|
mode->hsync = drm_mode_hsync(mode);
|
|
|
|
|
mode->vrefresh = drm_mode_vrefresh(mode);
|
|
|
|
|
drm_mode_set_name(mode);
|
2013-06-26 18:57:38 +03:00
|
|
|
}
|
|
|
|
|
|
2013-02-19 18:48:54 +01: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;
|
|
|
|
|
|
2013-06-13 00:54:58 +02:00
|
|
|
pipeconf = 0;
|
2013-02-19 18:48:54 +01:00
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
|
|
|
|
|
(intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
|
|
|
|
|
pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE;
|
2013-09-24 11:46:14 +02:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->double_wide)
|
2013-09-04 18:30:02 +03:00
|
|
|
pipeconf |= PIPECONF_DOUBLE_WIDE;
|
2013-02-19 18:48:54 +01:00
|
|
|
|
2013-04-24 14:57:17 +02:00
|
|
|
/* only g4x and later have fancy bpc/dither controls */
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2013-04-24 14:57:17 +02:00
|
|
|
/* Bspec claims that we can't use dithering for 30bpp pipes. */
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
|
2013-04-24 14:57:17 +02:00
|
|
|
pipeconf |= PIPECONF_DITHER_EN |
|
2013-02-19 18:48:54 +01:00
|
|
|
PIPECONF_DITHER_TYPE_SP;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
switch (intel_crtc->config->pipe_bpp) {
|
2013-04-24 14:57:17 +02:00
|
|
|
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-19 18:48:54 +01: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");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
|
2014-03-28 23:29:31 +02:00
|
|
|
if (INTEL_INFO(dev)->gen < 4 ||
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
|
2014-03-28 23:29:31 +02:00
|
|
|
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
|
|
|
|
|
else
|
|
|
|
|
pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
|
|
|
|
|
} else
|
2013-02-19 18:48:54 +01:00
|
|
|
pipeconf |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
|
|
|
|
intel_crtc->config->limited_color_range)
|
2013-06-13 00:54:58 +02:00
|
|
|
pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
|
2013-04-02 16:10:09 +03:00
|
|
|
|
2013-02-19 18:48:54 +01:00
|
|
|
I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
|
|
|
|
|
POSTING_READ(PIPECONF(intel_crtc->pipe));
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state)
|
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-07 14:24:08 -08:00
|
|
|
{
|
2014-10-20 13:46:44 +03:00
|
|
|
struct drm_device *dev = crtc->base.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-07 14:24:08 -08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-03-25 11:48:48 -07:00
|
|
|
int refclk, num_connectors = 0;
|
2015-06-18 10:30:23 +02:00
|
|
|
intel_clock_t clock;
|
|
|
|
|
bool ok;
|
2009-03-18 20:13:27 +08:00
|
|
|
const intel_limit_t *limit;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_atomic_state *state = crtc_state->base.state;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
int 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-07 14:24:08 -08:00
|
|
|
|
2015-05-15 13:34:29 +03:00
|
|
|
memset(&crtc_state->dpll_hw_state, 0,
|
|
|
|
|
sizeof(crtc_state->dpll_hw_state));
|
|
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
if (crtc_state->has_dsi_encoder)
|
|
|
|
|
return 0;
|
2009-02-13 20:56:52 -05:00
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
|
|
|
|
if (connector_state->crtc == &crtc->base)
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
if (!crtc_state->clock_set) {
|
2015-03-20 16:18:17 +02:00
|
|
|
refclk = i9xx_get_refclk(crtc_state, 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-07 14:24:08 -08:00
|
|
|
|
2013-08-27 15:12:23 +03: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.
|
|
|
|
|
*/
|
2015-03-20 16:18:17 +02:00
|
|
|
limit = intel_limit(crtc_state, refclk);
|
|
|
|
|
ok = dev_priv->display.find_dpll(limit, crtc_state,
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->port_clock,
|
2013-08-27 15:12:23 +03:00
|
|
|
refclk, NULL, &clock);
|
2013-09-13 11:03:09 +03:00
|
|
|
if (!ok) {
|
2013-08-27 15:12:23 +03:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
|
2013-09-13 11:03:09 +03:00
|
|
|
/* Compat-code for transition, will disappear. */
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll.n = clock.n;
|
|
|
|
|
crtc_state->dpll.m1 = clock.m1;
|
|
|
|
|
crtc_state->dpll.m2 = clock.m2;
|
|
|
|
|
crtc_state->dpll.p1 = clock.p1;
|
|
|
|
|
crtc_state->dpll.p2 = clock.p2;
|
2013-03-28 10:42:02 +01:00
|
|
|
}
|
2009-03-24 14:02:43 +08:00
|
|
|
|
2013-08-27 15:12:23 +03:00
|
|
|
if (IS_GEN2(dev)) {
|
2015-06-18 10:30:23 +02:00
|
|
|
i8xx_compute_dpll(crtc, crtc_state, NULL,
|
2015-06-18 10:30:24 +02:00
|
|
|
num_connectors);
|
2014-05-02 14:27:47 +03:00
|
|
|
} else if (IS_CHERRYVIEW(dev)) {
|
2015-06-18 10:30:24 +02:00
|
|
|
chv_compute_dpll(crtc, crtc_state);
|
2013-08-27 15:12:23 +03:00
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
2015-06-18 10:30:24 +02:00
|
|
|
vlv_compute_dpll(crtc, crtc_state);
|
2013-08-27 15:12:23 +03:00
|
|
|
} else {
|
2015-06-18 10:30:23 +02:00
|
|
|
i9xx_compute_dpll(crtc, crtc_state, NULL,
|
2015-06-18 10:30:24 +02:00
|
|
|
num_connectors);
|
2013-08-27 15:12:23 +03: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-07 14:24:08 -08:00
|
|
|
|
2014-04-24 23:55:04 +02:00
|
|
|
return 0;
|
2011-03-30 13:01:02 -07:00
|
|
|
}
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
static void i9xx_get_pfit_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-05-07 23:34:16 +02:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
2014-01-10 14:06:45 +02:00
|
|
|
if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
|
|
|
|
|
return;
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
tmp = I915_READ(PFIT_CONTROL);
|
2013-07-11 13:35:40 +02:00
|
|
|
if (!(tmp & PFIT_ENABLE))
|
|
|
|
|
return;
|
2013-05-07 23:34:16 +02:00
|
|
|
|
2013-07-11 13:35:40 +02:00
|
|
|
/* Check whether the pfit is attached to our pipe. */
|
2013-05-07 23:34:16 +02:00
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
|
|
|
|
if (crtc->pipe != PIPE_B)
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-11 13:35:40 +02:00
|
|
|
pipe_config->gmch_pfit.control = tmp;
|
2013-05-07 23:34:16 +02:00
|
|
|
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-09-20 11:29:32 -07:00
|
|
|
static void vlv_crtc_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-09-20 11:29:32 -07:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = pipe_config->cpu_transcoder;
|
|
|
|
|
intel_clock_t clock;
|
|
|
|
|
u32 mdiv;
|
2013-09-25 14:24:01 -07:00
|
|
|
int refclk = 100000;
|
2013-09-20 11:29:32 -07:00
|
|
|
|
2014-07-30 20:32:37 +05:30
|
|
|
/* In case of MIPI DPLL will not even be used */
|
|
|
|
|
if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2013-11-07 10:43:30 +08:00
|
|
|
mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2013-09-20 11:29:32 -07:00
|
|
|
|
|
|
|
|
clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
|
|
|
|
|
clock.m2 = mdiv & DPIO_M2DIV_MASK;
|
|
|
|
|
clock.n = (mdiv >> DPIO_N_SHIFT) & 0xf;
|
|
|
|
|
clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7;
|
|
|
|
|
clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
pipe_config->port_clock = vlv_calc_dpll_params(refclk, &clock);
|
2013-09-20 11:29:32 -07:00
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:52 +00:00
|
|
|
static void
|
|
|
|
|
i9xx_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_initial_plane_config *plane_config)
|
2014-03-07 08:57:49 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 val, base, offset;
|
|
|
|
|
int pipe = crtc->pipe, plane = crtc->plane;
|
|
|
|
|
int fourcc, pixel_format;
|
2015-03-23 11:10:32 +00:00
|
|
|
unsigned int aligned_height;
|
2015-01-20 12:51:46 +00:00
|
|
|
struct drm_framebuffer *fb;
|
2015-01-21 13:50:54 +00:00
|
|
|
struct intel_framebuffer *intel_fb;
|
2014-03-07 08:57:49 -08:00
|
|
|
|
2015-02-05 19:35:13 +00:00
|
|
|
val = I915_READ(DSPCNTR(plane));
|
|
|
|
|
if (!(val & DISPLAY_PLANE_ENABLE))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-01-21 14:07:19 +00:00
|
|
|
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
|
2015-01-21 13:50:54 +00:00
|
|
|
if (!intel_fb) {
|
2014-03-07 08:57:49 -08:00
|
|
|
DRM_DEBUG_KMS("failed to alloc fb\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 13:50:54 +00:00
|
|
|
fb = &intel_fb->base;
|
|
|
|
|
|
2015-02-10 17:16:09 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
if (val & DISPPLANE_TILED) {
|
2015-01-20 12:51:44 +00:00
|
|
|
plane_config->tiling = I915_TILING_X;
|
2015-02-10 17:16:09 +00:00
|
|
|
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-07 08:57:49 -08:00
|
|
|
|
|
|
|
|
pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
|
2015-01-20 12:51:50 +00:00
|
|
|
fourcc = i9xx_format_to_fourcc(pixel_format);
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->pixel_format = fourcc;
|
|
|
|
|
fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
|
2014-03-07 08:57:49 -08:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2015-01-20 12:51:44 +00:00
|
|
|
if (plane_config->tiling)
|
2014-03-07 08:57:49 -08:00
|
|
|
offset = I915_READ(DSPTILEOFF(plane));
|
|
|
|
|
else
|
|
|
|
|
offset = I915_READ(DSPLINOFF(plane));
|
|
|
|
|
base = I915_READ(DSPSURF(plane)) & 0xfffff000;
|
|
|
|
|
} else {
|
|
|
|
|
base = I915_READ(DSPADDR(plane));
|
|
|
|
|
}
|
|
|
|
|
plane_config->base = base;
|
|
|
|
|
|
|
|
|
|
val = I915_READ(PIPESRC(pipe));
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->width = ((val >> 16) & 0xfff) + 1;
|
|
|
|
|
fb->height = ((val >> 0) & 0xfff) + 1;
|
2014-03-07 08:57:49 -08:00
|
|
|
|
|
|
|
|
val = I915_READ(DSPSTRIDE(pipe));
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->pitches[0] = val & 0xffffffc0;
|
2014-03-07 08:57:49 -08:00
|
|
|
|
2015-01-20 12:51:46 +00:00
|
|
|
aligned_height = intel_fb_align_height(dev, fb->height,
|
2015-02-10 17:16:10 +00:00
|
|
|
fb->pixel_format,
|
|
|
|
|
fb->modifier[0]);
|
2014-03-07 08:57:49 -08:00
|
|
|
|
2015-02-10 23:12:27 +01:00
|
|
|
plane_config->size = fb->pitches[0] * aligned_height;
|
2014-03-07 08:57:49 -08:00
|
|
|
|
2015-01-20 12:51:48 +00:00
|
|
|
DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
|
|
|
|
pipe_name(pipe), plane, fb->width, fb->height,
|
|
|
|
|
fb->bits_per_pixel, base, fb->pitches[0],
|
|
|
|
|
plane_config->size);
|
2014-03-07 08:57:49 -08:00
|
|
|
|
2015-02-05 17:22:18 +00:00
|
|
|
plane_config->fb = intel_fb;
|
2014-03-07 08:57:49 -08:00
|
|
|
}
|
|
|
|
|
|
2014-04-09 13:28:22 +03:00
|
|
|
static void chv_crtc_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-04-09 13:28:22 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
int pipe = pipe_config->cpu_transcoder;
|
|
|
|
|
enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
|
|
|
|
intel_clock_t clock;
|
2015-07-02 14:29:58 +03:00
|
|
|
u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3;
|
2014-04-09 13:28:22 +03:00
|
|
|
int refclk = 100000;
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2014-04-09 13:28:22 +03:00
|
|
|
cmn_dw13 = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW13(port));
|
|
|
|
|
pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port));
|
|
|
|
|
pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port));
|
|
|
|
|
pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port));
|
2015-07-02 14:29:58 +03:00
|
|
|
pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2014-04-09 13:28:22 +03:00
|
|
|
|
|
|
|
|
clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
|
2015-07-02 14:29:58 +03:00
|
|
|
clock.m2 = (pll_dw0 & 0xff) << 22;
|
|
|
|
|
if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN)
|
|
|
|
|
clock.m2 |= pll_dw2 & 0x3fffff;
|
2014-04-09 13:28:22 +03:00
|
|
|
clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf;
|
|
|
|
|
clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7;
|
|
|
|
|
clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f;
|
|
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock);
|
2014-04-09 13:28:22 +03:00
|
|
|
}
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-03-28 10:42:00 +01:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv,
|
|
|
|
|
POWER_DOMAIN_PIPE(crtc->pipe)))
|
2014-03-05 16:20:55 +02:00
|
|
|
return false;
|
|
|
|
|
|
2013-07-04 12:01:15 +02:00
|
|
|
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
|
2013-06-07 23:11:08 +02:00
|
|
|
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
|
2013-05-22 00:50:22 +02:00
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
tmp = I915_READ(PIPECONF(crtc->pipe));
|
|
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2013-09-06 23:29:00 +03:00
|
|
|
switch (tmp & PIPECONF_BPC_MASK) {
|
|
|
|
|
case PIPECONF_6BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 18;
|
|
|
|
|
break;
|
|
|
|
|
case PIPECONF_8BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 24;
|
|
|
|
|
break;
|
|
|
|
|
case PIPECONF_10BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 30;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
|
|
|
|
(tmp & PIPECONF_COLOR_RANGE_SELECT))
|
2014-04-24 23:54:49 +02:00
|
|
|
pipe_config->limited_color_range = true;
|
|
|
|
|
|
2013-09-04 18:30:03 +03:00
|
|
|
if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
|
pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
|
|
|
|
|
|
2013-04-29 21:56:12 +02:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
i9xx_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
|
2013-06-06 12:45:25 +02:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
tmp = I915_READ(DPLL_MD(crtc->pipe));
|
|
|
|
|
pipe_config->pixel_multiplier =
|
|
|
|
|
((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
|
|
|
|
|
>> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
|
2013-06-05 13:34:28 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll_md = tmp;
|
2013-06-06 12:45:25 +02:00
|
|
|
} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
|
|
|
|
|
tmp = I915_READ(DPLL(crtc->pipe));
|
|
|
|
|
pipe_config->pixel_multiplier =
|
|
|
|
|
((tmp & SDVO_MULTIPLIER_MASK)
|
|
|
|
|
>> SDVO_MULTIPLIER_SHIFT_HIRES) + 1;
|
|
|
|
|
} else {
|
|
|
|
|
/* Note that on i915G/GM the pixel multiplier is in the sdvo
|
|
|
|
|
* port and will be fixed up in the encoder->get_config
|
|
|
|
|
* function. */
|
|
|
|
|
pipe_config->pixel_multiplier = 1;
|
|
|
|
|
}
|
2013-06-05 13:34:28 +02:00
|
|
|
pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
2014-09-05 21:52:42 +03:00
|
|
|
/*
|
|
|
|
|
* DPLL_DVO_2X_MODE must be enabled for both DPLLs
|
|
|
|
|
* on 830. Filter it out here so that we don't
|
|
|
|
|
* report errors due to that.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_I830(dev))
|
|
|
|
|
pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
|
|
|
|
|
|
2013-06-05 13:34:28 +02:00
|
|
|
pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
|
|
|
|
|
pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe));
|
2013-06-26 17:44:15 +03:00
|
|
|
} else {
|
|
|
|
|
/* Mask out read-only status bits. */
|
|
|
|
|
pipe_config->dpll_hw_state.dpll &= ~(DPLL_LOCK_VLV |
|
|
|
|
|
DPLL_PORTC_READY_MASK |
|
|
|
|
|
DPLL_PORTB_READY_MASK);
|
2013-06-05 13:34:28 +02:00
|
|
|
}
|
2013-06-06 12:45:25 +02:00
|
|
|
|
2014-04-09 13:28:22 +03:00
|
|
|
if (IS_CHERRYVIEW(dev))
|
|
|
|
|
chv_crtc_clock_get(crtc, pipe_config);
|
|
|
|
|
else if (IS_VALLEYVIEW(dev))
|
2013-09-20 11:29:32 -07:00
|
|
|
vlv_crtc_clock_get(crtc, pipe_config);
|
|
|
|
|
else
|
|
|
|
|
i9xx_crtc_clock_get(crtc, pipe_config);
|
2013-09-13 16:00:08 +03:00
|
|
|
|
2015-08-26 19:39:18 +03:00
|
|
|
/*
|
|
|
|
|
* Normally the dotclock is filled in by the encoder .get_config()
|
|
|
|
|
* but in case the pipe is enabled w/o any ports we need a sane
|
|
|
|
|
* default.
|
|
|
|
|
*/
|
|
|
|
|
pipe_config->base.adjusted_mode.crtc_clock =
|
|
|
|
|
pipe_config->port_clock / pipe_config->pixel_multiplier;
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-01 12:04:25 -02:00
|
|
|
static void ironlake_init_pch_refclk(struct drm_device *dev)
|
2011-08-03 12:59:20 -07:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_encoder *encoder;
|
2013-03-26 16:33:04 -07:00
|
|
|
u32 val, final;
|
2011-08-03 12:59:20 -07:00
|
|
|
bool has_lvds = false;
|
2011-09-22 12:01:57 -07:00
|
|
|
bool has_cpu_edp = false;
|
|
|
|
|
bool has_panel = false;
|
2011-09-26 14:29:12 -07:00
|
|
|
bool has_ck505 = false;
|
|
|
|
|
bool can_ssc = false;
|
2011-08-03 12:59:20 -07:00
|
|
|
|
|
|
|
|
/* We need to take the global config into account */
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
2011-09-22 12:01:57 -07:00
|
|
|
switch (encoder->type) {
|
|
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
|
has_panel = true;
|
|
|
|
|
has_lvds = true;
|
|
|
|
|
break;
|
|
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
|
|
has_panel = true;
|
2013-05-08 13:14:04 +03:00
|
|
|
if (enc_to_dig_port(&encoder->base)->port == PORT_A)
|
2011-09-22 12:01:57 -07:00
|
|
|
has_cpu_edp = true;
|
|
|
|
|
break;
|
2014-10-27 17:47:52 -02:00
|
|
|
default:
|
|
|
|
|
break;
|
2011-08-03 12:59:20 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-26 14:29:12 -07:00
|
|
|
if (HAS_PCH_IBX(dev)) {
|
2013-05-09 20:03:18 -03:00
|
|
|
has_ck505 = dev_priv->vbt.display_clock_mode;
|
2011-09-26 14:29:12 -07:00
|
|
|
can_ssc = has_ck505;
|
|
|
|
|
} else {
|
|
|
|
|
has_ck505 = false;
|
|
|
|
|
can_ssc = true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-08 13:14:04 +03:00
|
|
|
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
|
|
|
|
|
has_panel, has_lvds, has_ck505);
|
2011-08-03 12:59:20 -07: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-26 16:33:04 -07: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-03 12:59:20 -07:00
|
|
|
/* Always enable nonspread source */
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_NONSPREAD_SOURCE_MASK;
|
2011-08-03 12:59:20 -07:00
|
|
|
|
2011-09-26 14:29:12 -07:00
|
|
|
if (has_ck505)
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_NONSPREAD_CK505_ENABLE;
|
2011-09-26 14:29:12 -07:00
|
|
|
else
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_NONSPREAD_SOURCE_ENABLE;
|
2011-08-03 12:59:20 -07:00
|
|
|
|
2011-09-22 12:01:57 -07:00
|
|
|
if (has_panel) {
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
|
|
val |= DREF_SSC_SOURCE_ENABLE;
|
2011-08-03 12:59:20 -07:00
|
|
|
|
2011-09-22 12:01:57 -07:00
|
|
|
/* SSC must be turned on before enabling the CPU output */
|
2011-09-26 14:29:12 -07:00
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
2011-09-22 12:01:57 -07:00
|
|
|
DRM_DEBUG_KMS("Using SSC on panel\n");
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_SSC1_ENABLE;
|
2012-03-30 22:14:05 +02:00
|
|
|
} else
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_SSC1_ENABLE;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
|
|
|
|
/* Get SSC going before enabling the outputs */
|
2013-03-26 16:33:04 -07:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-22 12:01:57 -07:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
|
udelay(200);
|
|
|
|
|
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
2011-08-03 12:59:20 -07:00
|
|
|
|
|
|
|
|
/* Enable CPU source on CPU attached eDP */
|
2011-09-22 12:01:57 -07:00
|
|
|
if (has_cpu_edp) {
|
2011-09-26 14:29:12 -07:00
|
|
|
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
|
2011-09-22 12:01:57 -07:00
|
|
|
DRM_DEBUG_KMS("Using SSC on eDP\n");
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
2014-05-18 02:24:50 +02:00
|
|
|
} else
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
2011-09-22 12:01:57 -07:00
|
|
|
} else
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
2013-03-26 16:33:04 -07:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-22 12:01:57 -07:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
|
udelay(200);
|
|
|
|
|
} else {
|
|
|
|
|
DRM_DEBUG_KMS("Disabling SSC entirely\n");
|
|
|
|
|
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
|
|
|
|
/* Turn off CPU output */
|
2013-03-26 16:33:04 -07:00
|
|
|
val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
2013-03-26 16:33:04 -07:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-09-22 12:01:57 -07:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
|
udelay(200);
|
|
|
|
|
|
|
|
|
|
/* Turn off the SSC source */
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
|
|
val |= DREF_SSC_SOURCE_DISABLE;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
|
|
|
|
/* Turn off SSC1 */
|
2013-03-26 16:33:04 -07:00
|
|
|
val &= ~DREF_SSC1_ENABLE;
|
2011-09-22 12:01:57 -07:00
|
|
|
|
2013-03-26 16:33:04 -07:00
|
|
|
I915_WRITE(PCH_DREF_CONTROL, val);
|
2011-08-03 12:59:20 -07:00
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
|
|
udelay(200);
|
|
|
|
|
}
|
2013-03-26 16:33:04 -07:00
|
|
|
|
|
|
|
|
BUG_ON(val != final);
|
2011-08-03 12:59:20 -07:00
|
|
|
}
|
|
|
|
|
|
2013-07-18 18:51:11 -03:00
|
|
|
static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv)
|
2012-12-01 12:04:25 -02:00
|
|
|
{
|
2013-07-18 18:51:11 -03:00
|
|
|
uint32_t tmp;
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = I915_READ(SOUTH_CHICKEN2);
|
|
|
|
|
tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
|
|
|
|
|
I915_WRITE(SOUTH_CHICKEN2, tmp);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) &
|
|
|
|
|
FDI_MPHY_IOSFSB_RESET_STATUS, 100))
|
|
|
|
|
DRM_ERROR("FDI mPHY reset assert timeout\n");
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = I915_READ(SOUTH_CHICKEN2);
|
|
|
|
|
tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
|
|
|
|
|
I915_WRITE(SOUTH_CHICKEN2, tmp);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
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");
|
2013-07-18 18:51:11 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* WaMPhyProgramming:hsw */
|
|
|
|
|
static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
uint32_t tmp;
|
2012-12-01 12:04:25 -02:00
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
|
|
|
|
|
tmp &= ~(0xFF << 24);
|
|
|
|
|
tmp |= (0x12 << 24);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x8008, 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);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
|
|
|
|
|
tmp &= ~(7 << 13);
|
|
|
|
|
tmp |= (5 << 13);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
|
|
|
|
|
tmp &= ~(7 << 13);
|
|
|
|
|
tmp |= (5 << 13);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
|
|
|
|
|
tmp |= (1 << 27);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
|
|
|
|
|
tmp |= (1 << 27);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
|
|
|
|
|
tmp &= ~(0xF << 28);
|
|
|
|
|
tmp |= (4 << 28);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2013-07-12 14:19:36 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
|
|
|
|
|
tmp &= ~(0xF << 28);
|
|
|
|
|
tmp |= (4 << 28);
|
|
|
|
|
intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
|
2013-07-18 18:51:11 -03:00
|
|
|
}
|
|
|
|
|
|
2013-07-23 11:19:24 -03:00
|
|
|
/* Implements 3 different sequences from BSpec chapter "Display iCLK
|
|
|
|
|
* Programming" based on the parameters passed:
|
|
|
|
|
* - Sequence to enable CLKOUT_DP
|
|
|
|
|
* - Sequence to enable CLKOUT_DP without spread
|
|
|
|
|
* - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O
|
|
|
|
|
*/
|
|
|
|
|
static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread,
|
|
|
|
|
bool with_fdi)
|
2013-07-18 18:51:11 -03:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-07-23 11:19:24 -03:00
|
|
|
uint32_t reg, tmp;
|
|
|
|
|
|
|
|
|
|
if (WARN(with_fdi && !with_spread, "FDI requires downspread\n"))
|
|
|
|
|
with_spread = true;
|
2015-08-27 23:55:59 +03:00
|
|
|
if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n"))
|
2013-07-23 11:19:24 -03:00
|
|
|
with_fdi = false;
|
2013-07-18 18:51:11 -03:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2013-07-18 18:51:11 -03:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2013-07-23 11:19:24 -03:00
|
|
|
if (with_spread) {
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
|
|
|
|
|
tmp &= ~SBI_SSCCTL_PATHALT;
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
|
2013-07-18 18:51:11 -03:00
|
|
|
|
2013-07-23 11:19:24 -03:00
|
|
|
if (with_fdi) {
|
|
|
|
|
lpt_reset_fdi_mphy(dev_priv);
|
|
|
|
|
lpt_program_fdi_mphy(dev_priv);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-01 12:04:25 -02:00
|
|
|
|
2015-08-27 23:55:59 +03:00
|
|
|
reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
|
2013-07-23 11:19:24 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
|
|
|
|
|
tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
|
|
|
|
|
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
|
2013-01-22 15:33:27 +01:00
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2012-12-01 12:04:25 -02:00
|
|
|
}
|
|
|
|
|
|
2013-07-23 11:19:25 -03:00
|
|
|
/* Sequence to disable CLKOUT_DP */
|
|
|
|
|
static void lpt_disable_clkout_dp(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t reg, tmp;
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
2013-07-23 11:19:25 -03:00
|
|
|
|
2015-08-27 23:55:59 +03:00
|
|
|
reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
|
2013-07-23 11:19:25 -03:00
|
|
|
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
|
|
|
|
|
tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
|
|
|
|
|
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
|
|
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
|
|
|
|
|
if (!(tmp & SBI_SSCCTL_DISABLE)) {
|
|
|
|
|
if (!(tmp & SBI_SSCCTL_PATHALT)) {
|
|
|
|
|
tmp |= SBI_SSCCTL_PATHALT;
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
|
|
|
|
|
udelay(32);
|
|
|
|
|
}
|
|
|
|
|
tmp |= SBI_SSCCTL_DISABLE;
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 20:42:30 +03:00
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
2013-07-23 11:19:25 -03:00
|
|
|
}
|
|
|
|
|
|
2015-12-04 22:19:39 +02:00
|
|
|
#define BEND_IDX(steps) ((50 + (steps)) / 5)
|
|
|
|
|
|
|
|
|
|
static const uint16_t sscdivintphase[] = {
|
|
|
|
|
[BEND_IDX( 50)] = 0x3B23,
|
|
|
|
|
[BEND_IDX( 45)] = 0x3B23,
|
|
|
|
|
[BEND_IDX( 40)] = 0x3C23,
|
|
|
|
|
[BEND_IDX( 35)] = 0x3C23,
|
|
|
|
|
[BEND_IDX( 30)] = 0x3D23,
|
|
|
|
|
[BEND_IDX( 25)] = 0x3D23,
|
|
|
|
|
[BEND_IDX( 20)] = 0x3E23,
|
|
|
|
|
[BEND_IDX( 15)] = 0x3E23,
|
|
|
|
|
[BEND_IDX( 10)] = 0x3F23,
|
|
|
|
|
[BEND_IDX( 5)] = 0x3F23,
|
|
|
|
|
[BEND_IDX( 0)] = 0x0025,
|
|
|
|
|
[BEND_IDX( -5)] = 0x0025,
|
|
|
|
|
[BEND_IDX(-10)] = 0x0125,
|
|
|
|
|
[BEND_IDX(-15)] = 0x0125,
|
|
|
|
|
[BEND_IDX(-20)] = 0x0225,
|
|
|
|
|
[BEND_IDX(-25)] = 0x0225,
|
|
|
|
|
[BEND_IDX(-30)] = 0x0325,
|
|
|
|
|
[BEND_IDX(-35)] = 0x0325,
|
|
|
|
|
[BEND_IDX(-40)] = 0x0425,
|
|
|
|
|
[BEND_IDX(-45)] = 0x0425,
|
|
|
|
|
[BEND_IDX(-50)] = 0x0525,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Bend CLKOUT_DP
|
|
|
|
|
* steps -50 to 50 inclusive, in steps of 5
|
|
|
|
|
* < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
|
|
|
|
|
* change in clock period = -(steps / 10) * 5.787 ps
|
|
|
|
|
*/
|
|
|
|
|
static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
|
|
|
|
|
{
|
|
|
|
|
uint32_t tmp;
|
|
|
|
|
int idx = BEND_IDX(steps);
|
|
|
|
|
|
|
|
|
|
if (WARN_ON(steps % 5 != 0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->sb_lock);
|
|
|
|
|
|
|
|
|
|
if (steps % 10 != 0)
|
|
|
|
|
tmp = 0xAAAAAAAB;
|
|
|
|
|
else
|
|
|
|
|
tmp = 0x00000000;
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
|
|
|
|
|
|
|
|
|
|
tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
|
|
|
|
|
tmp &= 0xffff0000;
|
|
|
|
|
tmp |= sscdivintphase[idx];
|
|
|
|
|
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
|
|
|
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->sb_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef BEND_IDX
|
|
|
|
|
|
2013-07-12 14:19:38 -03:00
|
|
|
static void lpt_init_pch_refclk(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
bool has_vga = false;
|
|
|
|
|
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
2013-07-12 14:19:38 -03:00
|
|
|
switch (encoder->type) {
|
|
|
|
|
case INTEL_OUTPUT_ANALOG:
|
|
|
|
|
has_vga = true;
|
|
|
|
|
break;
|
2014-10-27 17:47:52 -02:00
|
|
|
default:
|
|
|
|
|
break;
|
2013-07-12 14:19:38 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-04 22:19:39 +02:00
|
|
|
if (has_vga) {
|
|
|
|
|
lpt_bend_clkout_dp(to_i915(dev), 0);
|
2013-07-23 11:19:25 -03:00
|
|
|
lpt_enable_clkout_dp(dev, true, true);
|
2015-12-04 22:19:39 +02:00
|
|
|
} else {
|
2013-07-23 11:19:25 -03:00
|
|
|
lpt_disable_clkout_dp(dev);
|
2015-12-04 22:19:39 +02:00
|
|
|
}
|
2013-07-12 14:19:38 -03:00
|
|
|
}
|
|
|
|
|
|
2012-12-01 12:04:25 -02: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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:19 +02:00
|
|
|
static int ironlake_get_refclk(struct intel_crtc_state *crtc_state)
|
2011-09-02 13:03:05 -07:00
|
|
|
{
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_device *dev = crtc_state->base.crtc->dev;
|
2011-09-02 13:03:05 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_atomic_state *state = crtc_state->base.state;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
2011-09-02 13:03:05 -07:00
|
|
|
struct intel_encoder *encoder;
|
2015-03-20 16:18:19 +02:00
|
|
|
int num_connectors = 0, i;
|
2011-09-02 13:03:05 -07:00
|
|
|
bool is_lvds = false;
|
|
|
|
|
|
2015-04-21 17:12:59 +03:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
2015-03-20 16:18:19 +02:00
|
|
|
if (connector_state->crtc != crtc_state->base.crtc)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
|
2011-09-02 13:03:05 -07:00
|
|
|
switch (encoder->type) {
|
|
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
|
is_lvds = true;
|
|
|
|
|
break;
|
2014-10-27 17:47:52 -02:00
|
|
|
default:
|
|
|
|
|
break;
|
2011-09-02 13:03:05 -07:00
|
|
|
}
|
|
|
|
|
num_connectors++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
2013-12-09 18:54:16 +02:00
|
|
|
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
|
2013-05-09 20:03:18 -03:00
|
|
|
dev_priv->vbt.lvds_ssc_freq);
|
2013-12-09 18:54:16 +02:00
|
|
|
return dev_priv->vbt.lvds_ssc_freq;
|
2011-09-02 13:03:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 120000;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-19 11:24:36 +02: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-07 14:24:08 -08:00
|
|
|
{
|
2012-09-12 10:06:29 -03: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-07 14:24:08 -08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
int pipe = intel_crtc->pipe;
|
2012-09-12 10:06:29 -03:00
|
|
|
uint32_t val;
|
|
|
|
|
|
2013-06-13 00:54:57 +02:00
|
|
|
val = 0;
|
2012-09-12 10:06:29 -03:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
switch (intel_crtc->config->pipe_bpp) {
|
2012-09-12 10:06:29 -03:00
|
|
|
case 18:
|
2012-12-17 11:21:38 +01:00
|
|
|
val |= PIPECONF_6BPC;
|
2012-09-12 10:06:29 -03:00
|
|
|
break;
|
|
|
|
|
case 24:
|
2012-12-17 11:21:38 +01:00
|
|
|
val |= PIPECONF_8BPC;
|
2012-09-12 10:06:29 -03:00
|
|
|
break;
|
|
|
|
|
case 30:
|
2012-12-17 11:21:38 +01:00
|
|
|
val |= PIPECONF_10BPC;
|
2012-09-12 10:06:29 -03:00
|
|
|
break;
|
|
|
|
|
case 36:
|
2012-12-17 11:21:38 +01:00
|
|
|
val |= PIPECONF_12BPC;
|
2012-09-12 10:06:29 -03:00
|
|
|
break;
|
|
|
|
|
default:
|
2012-09-20 18:36:03 -03:00
|
|
|
/* Case prevented by intel_choose_pipe_bpp_dither. */
|
|
|
|
|
BUG();
|
2012-09-12 10:06:29 -03:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->dither)
|
2012-09-12 10:06:29 -03:00
|
|
|
val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
2012-09-12 10:06:29 -03:00
|
|
|
val |= PIPECONF_INTERLACED_ILK;
|
|
|
|
|
else
|
|
|
|
|
val |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->limited_color_range)
|
2013-01-17 16:31:28 +02:00
|
|
|
val |= PIPECONF_COLOR_RANGE_SELECT;
|
|
|
|
|
|
2012-09-12 10:06:29 -03:00
|
|
|
I915_WRITE(PIPECONF(pipe), val);
|
|
|
|
|
POSTING_READ(PIPECONF(pipe));
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-18 19:11:38 +02: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 00:44:56 +01:00
|
|
|
static void intel_set_pipe_csc(struct drm_crtc *crtc)
|
2013-01-18 19:11:38 +02: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.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->limited_color_range)
|
2013-01-18 19:11:38 +02: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;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->limited_color_range)
|
2013-11-28 22:10:38 +02:00
|
|
|
postoff = (16 * (1 << 12) / 255) & 0x1fff;
|
2013-01-18 19:11:38 +02:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->limited_color_range)
|
2013-01-18 19:11:38 +02:00
|
|
|
mode |= CSC_BLACK_SCREEN_OFFSET;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(PIPE_CSC_MODE(pipe), mode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-19 11:24:36 +02:00
|
|
|
static void haswell_set_pipeconf(struct drm_crtc *crtc)
|
2012-10-05 12:05:57 -03:00
|
|
|
{
|
2013-11-02 21:07:38 -07:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-10-05 12:05:57 -03:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2013-11-02 21:07:38 -07:00
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
2015-01-15 14:55:25 +02:00
|
|
|
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
|
2012-10-05 12:05:57 -03:00
|
|
|
uint32_t val;
|
|
|
|
|
|
2013-06-13 00:54:59 +02:00
|
|
|
val = 0;
|
2012-10-05 12:05:57 -03:00
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (IS_HASWELL(dev) && intel_crtc->config->dither)
|
2012-10-05 12:05:57 -03:00
|
|
|
val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
2012-10-05 12:05:57 -03:00
|
|
|
val |= PIPECONF_INTERLACED_ILK;
|
|
|
|
|
else
|
|
|
|
|
val |= PIPECONF_PROGRESSIVE;
|
|
|
|
|
|
2012-10-23 18:29:59 -02:00
|
|
|
I915_WRITE(PIPECONF(cpu_transcoder), val);
|
|
|
|
|
POSTING_READ(PIPECONF(cpu_transcoder));
|
2013-06-13 00:54:59 +02:00
|
|
|
|
|
|
|
|
I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
|
|
|
|
|
POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
|
2013-11-02 21:07:38 -07:00
|
|
|
|
2014-04-08 15:46:53 +05:30
|
|
|
if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
|
2013-11-02 21:07:38 -07:00
|
|
|
val = 0;
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
switch (intel_crtc->config->pipe_bpp) {
|
2013-11-02 21:07:38 -07:00
|
|
|
case 18:
|
|
|
|
|
val |= PIPEMISC_DITHER_6_BPC;
|
|
|
|
|
break;
|
|
|
|
|
case 24:
|
|
|
|
|
val |= PIPEMISC_DITHER_8_BPC;
|
|
|
|
|
break;
|
|
|
|
|
case 30:
|
|
|
|
|
val |= PIPEMISC_DITHER_10_BPC;
|
|
|
|
|
break;
|
|
|
|
|
case 36:
|
|
|
|
|
val |= PIPEMISC_DITHER_12_BPC;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* Case prevented by pipe_config_set_bpp. */
|
|
|
|
|
BUG();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:25 +02:00
|
|
|
if (intel_crtc->config->dither)
|
2013-11-02 21:07:38 -07:00
|
|
|
val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
|
|
|
|
|
|
|
|
|
|
I915_WRITE(PIPEMISC(pipe), val);
|
|
|
|
|
}
|
2012-10-05 12:05:57 -03:00
|
|
|
}
|
|
|
|
|
|
2012-09-12 10:06:34 -03:00
|
|
|
static bool ironlake_compute_clocks(struct drm_crtc *crtc,
|
2015-01-15 14:55:23 +02:00
|
|
|
struct intel_crtc_state *crtc_state,
|
2012-09-12 10:06:34 -03:00
|
|
|
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;
|
|
|
|
|
int refclk;
|
2009-03-18 20:13:27 +08:00
|
|
|
const intel_limit_t *limit;
|
2015-06-18 10:30:23 +02:00
|
|
|
bool 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-07 14:24:08 -08:00
|
|
|
|
2015-03-20 16:18:19 +02:00
|
|
|
refclk = ironlake_get_refclk(crtc_state);
|
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-07 14: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.
|
|
|
|
|
*/
|
2015-03-20 16:18:17 +02:00
|
|
|
limit = intel_limit(crtc_state, refclk);
|
|
|
|
|
ret = dev_priv->display.find_dpll(limit, crtc_state,
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->port_clock,
|
2013-06-03 22:40:22 +02:00
|
|
|
refclk, NULL, clock);
|
2012-09-12 10:06:34 -03:00
|
|
|
if (!ret)
|
|
|
|
|
return false;
|
2010-07-09 08:45:04 +01:00
|
|
|
|
2012-09-12 10:06:34 -03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-29 11:29:32 -02: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;
|
2014-02-27 14:23:14 +02:00
|
|
|
return DIV_ROUND_UP(bps, link_bw * 8);
|
2012-11-29 11:29:32 -02:00
|
|
|
}
|
|
|
|
|
|
2013-04-20 17:19:46 +02:00
|
|
|
static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
|
drm/i915: clear up the fdi/dp set_m_n confusion
There's a rather decent confusion going on around transcoder m_n
values. So let's clarify:
- All dp encoders need this, either on the pch transcoder if it's a
pch port, or on the cpu transcoder/pipe if it's a cpu port.
- fdi links need to have the right m_n values for the fdi link set in
the cpu transcoder.
To handle the pch vs transcoder stuff a bit better, extract transcoder
set_m_n helpers. To make them simpler, set intel_crtc->cpu_transcoder
als in ironlake_crtc_mode_set, so that gen5+ (where the cpu m_n
registers are all at the same offset) can use it.
Haswell modeset is decently confused about dp vs. edp vs. fdi. dp vs.
edp works exactly the same as dp (since there's no pch dp any more),
so use that as a check. And only set up the fdi m_n values if we
really have a pch encoder present (which means we have a VGA encoder).
On ilk+ we've called ironlake_set_m_n both for cpu_edp and for pch
encoders. Now that dp_set_m_n handles all dp links (thanks to the
pch encoder check), we can ditch the cpu_edp stuff from the
fdi_set_m_n function.
Since the dp_m_n values are not readily available, we need to
carefully coax the edp values out of the encoder. Hence we can't (yet)
kill this superflous complexity.
v2: Rebase on top of the ivb fdi B/C check patch - we need to properly
clear intel_crtc->fdi_lane, otherwise those checks will misfire.
v3: Rebased on top of a s/IS_HASWELL/HAS_DDI/ patch from Paulo Zanoni.
v4: Drop the addition of has_dp_encoder, it's in the wrong patch (Jesse).
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-04-02 23:38:10 +02:00
|
|
|
{
|
2013-04-20 17:19:46 +02:00
|
|
|
return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
|
2012-09-20 18:36:04 -03:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 18:36:05 -03:00
|
|
|
static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
2015-01-15 14:55:23 +02:00
|
|
|
struct intel_crtc_state *crtc_state,
|
2013-04-20 17:19:46 +02:00
|
|
|
u32 *fp,
|
2013-04-04 22:20:34 +02: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-07 14:24:08 -08:00
|
|
|
{
|
2012-09-20 18:36:05 -03: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-07 14:24:08 -08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_atomic_state *state = crtc_state->base.state;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2015-03-20 16:18:19 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
struct intel_encoder *encoder;
|
2012-09-20 18:36:05 -03:00
|
|
|
uint32_t dpll;
|
2015-03-20 16:18:19 +02:00
|
|
|
int factor, num_connectors = 0, i;
|
2013-04-30 14:01:45 +02: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-07 14:24:08 -08:00
|
|
|
|
2015-04-21 17:12:59 +03:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
2015-03-20 16:18:19 +02:00
|
|
|
if (connector_state->crtc != crtc_state->base.crtc)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
|
|
is_lvds = true;
|
|
|
|
|
break;
|
|
|
|
|
case INTEL_OUTPUT_SDVO:
|
2009-01-02 13: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-07 14:24:08 -08:00
|
|
|
is_sdvo = true;
|
|
|
|
|
break;
|
2014-10-27 17:47:52 -02:00
|
|
|
default:
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
2009-02-13 20:56:52 -05:00
|
|
|
|
2010-03-25 11:48:48 -07: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2010-12-03 21:35:48 +00:00
|
|
|
/* Enable autotuning of the PLL clock (if permissible) */
|
2011-03-30 13:01:07 -07:00
|
|
|
factor = 21;
|
|
|
|
|
if (is_lvds) {
|
|
|
|
|
if ((intel_panel_use_ssc(dev_priv) &&
|
2013-12-09 18:54:16 +02:00
|
|
|
dev_priv->vbt.lvds_ssc_freq == 100000) ||
|
2013-04-04 22:20:33 +02:00
|
|
|
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
|
2011-03-30 13:01:07 -07:00
|
|
|
factor = 25;
|
2015-01-15 14:55:23 +02:00
|
|
|
} else if (crtc_state->sdvo_tv_clock)
|
2011-03-30 13:01:07 -07:00
|
|
|
factor = 20;
|
2010-12-03 21:35:48 +00:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor))
|
2013-04-04 22:20:32 +02:00
|
|
|
*fp |= FP_CB_TUNE;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2013-04-04 22:20:34 +02:00
|
|
|
if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
|
|
|
|
|
*fp2 |= FP_CB_TUNE;
|
|
|
|
|
|
2010-09-11 13:48:45 +01:00
|
|
|
dpll = 0;
|
2009-06-05 15:38:42 +08:00
|
|
|
|
2011-03-30 13:01:08 -07:00
|
|
|
if (is_lvds)
|
|
|
|
|
dpll |= DPLLB_MODE_LVDS;
|
|
|
|
|
else
|
|
|
|
|
dpll |= DPLLB_MODE_DAC_SERIAL;
|
2013-04-19 11:14:37 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
dpll |= (crtc_state->pixel_multiplier - 1)
|
2013-06-01 17:17:04 +02:00
|
|
|
<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
|
2013-04-19 11:14:37 +02:00
|
|
|
|
|
|
|
|
if (is_sdvo)
|
2013-07-06 12:52:05 +02:00
|
|
|
dpll |= DPLL_SDVO_HIGH_SPEED;
|
2015-01-15 14:55:23 +02:00
|
|
|
if (crtc_state->has_dp_encoder)
|
2013-07-06 12:52:05 +02:00
|
|
|
dpll |= DPLL_SDVO_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-07 14:24:08 -08:00
|
|
|
|
2011-03-30 13:01:08 -07:00
|
|
|
/* compute bitmask from p1 value */
|
2015-01-15 14:55:23 +02:00
|
|
|
dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
2011-03-30 13:01:08 -07:00
|
|
|
/* also FPA1 */
|
2015-01-15 14:55:23 +02:00
|
|
|
dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
2011-03-30 13:01:08 -07:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
switch (crtc_state->dpll.p2) {
|
2011-03-30 13:01:08 -07: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-04-30 14:01:42 +02:00
|
|
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
|
2009-02-13 20:56:52 -05: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-07 14:24:08 -08:00
|
|
|
else
|
|
|
|
|
dpll |= PLL_REF_INPUT_DREFCLK;
|
|
|
|
|
|
2013-06-05 13:34:21 +02:00
|
|
|
return dpll | DPLL_VCO_ENABLE;
|
2012-09-20 18:36:05 -03:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state)
|
2012-09-20 18:36:05 -03:00
|
|
|
{
|
2014-10-20 13:46:44 +03:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2012-09-20 18:36:05 -03:00
|
|
|
intel_clock_t clock, reduced_clock;
|
2013-04-19 11:14:31 +02:00
|
|
|
u32 dpll = 0, fp = 0, fp2 = 0;
|
2012-09-20 18:36:06 -03:00
|
|
|
bool ok, has_reduced_clock = false;
|
2013-03-28 10:41:59 +01:00
|
|
|
bool is_lvds = false;
|
2013-06-07 23:10:03 +02:00
|
|
|
struct intel_shared_dpll *pll;
|
2012-09-20 18:36:05 -03:00
|
|
|
|
2015-05-15 13:34:29 +03:00
|
|
|
memset(&crtc_state->dpll_hw_state, 0,
|
|
|
|
|
sizeof(crtc_state->dpll_hw_state));
|
|
|
|
|
|
2015-11-25 16:35:30 +02:00
|
|
|
is_lvds = intel_pipe_will_have_type(crtc_state, 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-07 14:24:08 -08:00
|
|
|
|
2012-10-05 12:05:56 -03:00
|
|
|
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
|
|
|
|
|
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
|
2011-03-30 13:01:08 -07:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
ok = ironlake_compute_clocks(&crtc->base, crtc_state, &clock,
|
2012-09-20 18:36:05 -03:00
|
|
|
&has_reduced_clock, &reduced_clock);
|
2015-01-15 14:55:23 +02:00
|
|
|
if (!ok && !crtc_state->clock_set) {
|
2012-09-20 18:36:05 -03:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
2013-03-28 10:42:02 +01:00
|
|
|
/* Compat-code for transition, will disappear. */
|
2015-01-15 14:55:23 +02:00
|
|
|
if (!crtc_state->clock_set) {
|
|
|
|
|
crtc_state->dpll.n = clock.n;
|
|
|
|
|
crtc_state->dpll.m1 = clock.m1;
|
|
|
|
|
crtc_state->dpll.m2 = clock.m2;
|
|
|
|
|
crtc_state->dpll.p1 = clock.p1;
|
|
|
|
|
crtc_state->dpll.p2 = clock.p2;
|
2013-03-28 10:42:02 +01: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-07 14:24:08 -08:00
|
|
|
|
2012-10-05 12:05:56 -03:00
|
|
|
/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
|
2015-01-15 14:55:23 +02:00
|
|
|
if (crtc_state->has_pch_encoder) {
|
|
|
|
|
fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
|
2013-04-19 11:14:31 +02:00
|
|
|
if (has_reduced_clock)
|
2013-04-20 17:19:46 +02:00
|
|
|
fp2 = i9xx_dpll_compute_fp(&reduced_clock);
|
2013-04-19 11:14:31 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
dpll = ironlake_compute_dpll(crtc, crtc_state,
|
2013-04-19 11:14:31 +02:00
|
|
|
&fp, &reduced_clock,
|
|
|
|
|
has_reduced_clock ? &fp2 : NULL);
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.dpll = dpll;
|
|
|
|
|
crtc_state->dpll_hw_state.fp0 = fp;
|
2013-06-05 13:34:20 +02:00
|
|
|
if (has_reduced_clock)
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.fp1 = fp2;
|
2013-06-05 13:34:20 +02:00
|
|
|
else
|
2015-01-15 14:55:23 +02:00
|
|
|
crtc_state->dpll_hw_state.fp1 = fp;
|
2013-06-05 13:34:20 +02:00
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
pll = intel_get_shared_dpll(crtc, crtc_state);
|
2012-04-20 17:11:53 +01:00
|
|
|
if (pll == NULL) {
|
2013-04-17 17:48:49 +03:00
|
|
|
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
|
2014-10-20 13:46:44 +03:00
|
|
|
pipe_name(crtc->pipe));
|
2011-10-12 09:51:31 -07:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
2014-10-29 11:32:35 +02: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-07 14:24:08 -08:00
|
|
|
|
2015-03-24 12:40:09 -07:00
|
|
|
if (is_lvds && has_reduced_clock)
|
2014-10-20 13:46:44 +03:00
|
|
|
crtc->lowfreq_avail = true;
|
2013-06-05 13:34:22 +02:00
|
|
|
else
|
2014-10-20 13:46:44 +03:00
|
|
|
crtc->lowfreq_avail = false;
|
2013-06-07 23:10:03 +02:00
|
|
|
|
2014-04-24 23:55:04 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-09-10 17:02:54 +03:00
|
|
|
static void intel_pch_transcoder_get_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;
|
|
|
|
|
enum pipe pipe = crtc->pipe;
|
|
|
|
|
|
|
|
|
|
m_n->link_m = I915_READ(PCH_TRANS_LINK_M1(pipe));
|
|
|
|
|
m_n->link_n = I915_READ(PCH_TRANS_LINK_N1(pipe));
|
|
|
|
|
m_n->gmch_m = I915_READ(PCH_TRANS_DATA_M1(pipe))
|
|
|
|
|
& ~TU_SIZE_MASK;
|
|
|
|
|
m_n->gmch_n = I915_READ(PCH_TRANS_DATA_N1(pipe));
|
|
|
|
|
m_n->tu = ((I915_READ(PCH_TRANS_DATA_M1(pipe))
|
|
|
|
|
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
|
|
|
|
|
enum transcoder transcoder,
|
2014-08-05 07:51:23 -07:00
|
|
|
struct intel_link_m_n *m_n,
|
|
|
|
|
struct intel_link_m_n *m2_n2)
|
2013-04-04 13:28:53 +02:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-09-10 17:02:54 +03:00
|
|
|
enum pipe pipe = crtc->pipe;
|
2013-04-04 13:28:53 +02:00
|
|
|
|
2013-09-10 17:02:54 +03:00
|
|
|
if (INTEL_INFO(dev)->gen >= 5) {
|
|
|
|
|
m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder));
|
|
|
|
|
m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder));
|
|
|
|
|
m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
|
|
|
|
|
& ~TU_SIZE_MASK;
|
|
|
|
|
m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
|
|
|
|
|
m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder))
|
|
|
|
|
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
|
2014-08-05 07:51:23 -07:00
|
|
|
/* Read M2_N2 registers only for gen < 8 (M2_N2 available for
|
|
|
|
|
* gen < 8) and if DRRS is supported (to make sure the
|
|
|
|
|
* registers are not unnecessarily read).
|
|
|
|
|
*/
|
|
|
|
|
if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
|
2015-01-15 14:55:25 +02:00
|
|
|
crtc->config->has_drrs) {
|
2014-08-05 07:51:23 -07:00
|
|
|
m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
|
|
|
|
|
m2_n2->link_n = I915_READ(PIPE_LINK_N2(transcoder));
|
|
|
|
|
m2_n2->gmch_m = I915_READ(PIPE_DATA_M2(transcoder))
|
|
|
|
|
& ~TU_SIZE_MASK;
|
|
|
|
|
m2_n2->gmch_n = I915_READ(PIPE_DATA_N2(transcoder));
|
|
|
|
|
m2_n2->tu = ((I915_READ(PIPE_DATA_M2(transcoder))
|
|
|
|
|
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
|
|
|
|
|
}
|
2013-09-10 17:02:54 +03:00
|
|
|
} else {
|
|
|
|
|
m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe));
|
|
|
|
|
m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe));
|
|
|
|
|
m_n->gmch_m = I915_READ(PIPE_DATA_M_G4X(pipe))
|
|
|
|
|
& ~TU_SIZE_MASK;
|
|
|
|
|
m_n->gmch_n = I915_READ(PIPE_DATA_N_G4X(pipe));
|
|
|
|
|
m_n->tu = ((I915_READ(PIPE_DATA_M_G4X(pipe))
|
|
|
|
|
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_dp_get_m_n(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-09-10 17:02:54 +03:00
|
|
|
{
|
2015-01-15 14:55:24 +02:00
|
|
|
if (pipe_config->has_pch_encoder)
|
2013-09-10 17:02:54 +03:00
|
|
|
intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
|
|
|
|
|
else
|
|
|
|
|
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
|
2014-08-05 07:51:23 -07:00
|
|
|
&pipe_config->dp_m_n,
|
|
|
|
|
&pipe_config->dp_m2_n2);
|
2013-09-10 17:02:54 +03:00
|
|
|
}
|
2013-04-04 13:28:53 +02:00
|
|
|
|
2013-09-10 17:02:54 +03:00
|
|
|
static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-09-10 17:02:54 +03:00
|
|
|
{
|
|
|
|
|
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
|
2014-08-05 07:51:23 -07:00
|
|
|
&pipe_config->fdi_m_n, NULL);
|
2013-04-04 13:28:53 +02:00
|
|
|
}
|
|
|
|
|
|
2014-11-13 17:51:47 +00:00
|
|
|
static void skylake_get_pfit_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-11-13 17:51:47 +00:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-04-07 15:28:45 -07:00
|
|
|
struct intel_crtc_scaler_state *scaler_state = &pipe_config->scaler_state;
|
|
|
|
|
uint32_t ps_ctrl = 0;
|
|
|
|
|
int id = -1;
|
|
|
|
|
int i;
|
2014-11-13 17:51:47 +00:00
|
|
|
|
2015-04-07 15:28:45 -07:00
|
|
|
/* find scaler attached to this pipe */
|
|
|
|
|
for (i = 0; i < crtc->num_scalers; i++) {
|
|
|
|
|
ps_ctrl = I915_READ(SKL_PS_CTRL(crtc->pipe, i));
|
|
|
|
|
if (ps_ctrl & PS_SCALER_EN && !(ps_ctrl & PS_PLANE_SEL_MASK)) {
|
|
|
|
|
id = i;
|
|
|
|
|
pipe_config->pch_pfit.enabled = true;
|
|
|
|
|
pipe_config->pch_pfit.pos = I915_READ(SKL_PS_WIN_POS(crtc->pipe, i));
|
|
|
|
|
pipe_config->pch_pfit.size = I915_READ(SKL_PS_WIN_SZ(crtc->pipe, i));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-11-13 17:51:47 +00:00
|
|
|
|
2015-04-07 15:28:45 -07:00
|
|
|
scaler_state->scaler_id = id;
|
|
|
|
|
if (id >= 0) {
|
|
|
|
|
scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
|
|
|
|
|
} else {
|
|
|
|
|
scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
|
2014-11-13 17:51:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:52 +00:00
|
|
|
static void
|
|
|
|
|
skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_initial_plane_config *plane_config)
|
2015-01-20 12:51:51 +00:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-02-27 11:15:21 +00:00
|
|
|
u32 val, base, offset, stride_mult, tiling;
|
2015-01-20 12:51:51 +00:00
|
|
|
int pipe = crtc->pipe;
|
|
|
|
|
int fourcc, pixel_format;
|
2015-03-23 11:10:32 +00:00
|
|
|
unsigned int aligned_height;
|
2015-01-20 12:51:51 +00:00
|
|
|
struct drm_framebuffer *fb;
|
2015-01-21 13:50:54 +00:00
|
|
|
struct intel_framebuffer *intel_fb;
|
2015-01-20 12:51:51 +00:00
|
|
|
|
2015-01-21 14:07:19 +00:00
|
|
|
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
|
2015-01-21 13:50:54 +00:00
|
|
|
if (!intel_fb) {
|
2015-01-20 12:51:51 +00:00
|
|
|
DRM_DEBUG_KMS("failed to alloc fb\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 13:50:54 +00:00
|
|
|
fb = &intel_fb->base;
|
|
|
|
|
|
2015-01-20 12:51:51 +00:00
|
|
|
val = I915_READ(PLANE_CTL(pipe, 0));
|
2015-02-05 19:35:13 +00:00
|
|
|
if (!(val & PLANE_CTL_ENABLE))
|
|
|
|
|
goto error;
|
|
|
|
|
|
2015-01-20 12:51:51 +00:00
|
|
|
pixel_format = val & PLANE_CTL_FORMAT_MASK;
|
|
|
|
|
fourcc = skl_format_to_fourcc(pixel_format,
|
|
|
|
|
val & PLANE_CTL_ORDER_RGBX,
|
|
|
|
|
val & PLANE_CTL_ALPHA_MASK);
|
|
|
|
|
fb->pixel_format = fourcc;
|
|
|
|
|
fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
|
|
|
|
|
|
2015-02-27 11:15:21 +00:00
|
|
|
tiling = val & PLANE_CTL_TILED_MASK;
|
|
|
|
|
switch (tiling) {
|
|
|
|
|
case PLANE_CTL_TILED_LINEAR:
|
|
|
|
|
fb->modifier[0] = DRM_FORMAT_MOD_NONE;
|
|
|
|
|
break;
|
|
|
|
|
case PLANE_CTL_TILED_X:
|
|
|
|
|
plane_config->tiling = I915_TILING_X;
|
|
|
|
|
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
|
|
|
|
break;
|
|
|
|
|
case PLANE_CTL_TILED_Y:
|
|
|
|
|
fb->modifier[0] = I915_FORMAT_MOD_Y_TILED;
|
|
|
|
|
break;
|
|
|
|
|
case PLANE_CTL_TILED_YF:
|
|
|
|
|
fb->modifier[0] = I915_FORMAT_MOD_Yf_TILED;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
MISSING_CASE(tiling);
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:51 +00:00
|
|
|
base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000;
|
|
|
|
|
plane_config->base = base;
|
|
|
|
|
|
|
|
|
|
offset = I915_READ(PLANE_OFFSET(pipe, 0));
|
|
|
|
|
|
|
|
|
|
val = I915_READ(PLANE_SIZE(pipe, 0));
|
|
|
|
|
fb->height = ((val >> 16) & 0xfff) + 1;
|
|
|
|
|
fb->width = ((val >> 0) & 0x1fff) + 1;
|
|
|
|
|
|
|
|
|
|
val = I915_READ(PLANE_STRIDE(pipe, 0));
|
2015-02-27 11:15:21 +00:00
|
|
|
stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
|
|
fb->pixel_format);
|
2015-01-20 12:51:51 +00:00
|
|
|
fb->pitches[0] = (val & 0x3ff) * stride_mult;
|
|
|
|
|
|
|
|
|
|
aligned_height = intel_fb_align_height(dev, fb->height,
|
2015-02-10 17:16:10 +00:00
|
|
|
fb->pixel_format,
|
|
|
|
|
fb->modifier[0]);
|
2015-01-20 12:51:51 +00:00
|
|
|
|
2015-02-10 23:12:27 +01:00
|
|
|
plane_config->size = fb->pitches[0] * aligned_height;
|
2015-01-20 12:51:51 +00:00
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
|
|
|
|
pipe_name(pipe), fb->width, fb->height,
|
|
|
|
|
fb->bits_per_pixel, base, fb->pitches[0],
|
|
|
|
|
plane_config->size);
|
|
|
|
|
|
2015-02-05 17:22:18 +00:00
|
|
|
plane_config->fb = intel_fb;
|
2015-01-20 12:51:51 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
kfree(fb);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
static void ironlake_get_pfit_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-05-07 23:34:16 +02:00
|
|
|
{
|
|
|
|
|
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) {
|
2013-08-27 17:04:17 +01:00
|
|
|
pipe_config->pch_pfit.enabled = true;
|
2013-05-07 23:34:16 +02:00
|
|
|
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-06-01 17:16:23 +02:00
|
|
|
|
|
|
|
|
/* We currently do not free assignements of panel fitters on
|
|
|
|
|
* ivb/hsw (since we don't use the higher upscaling modes which
|
|
|
|
|
* differentiates them) so just WARN about this case for now. */
|
|
|
|
|
if (IS_GEN7(dev)) {
|
|
|
|
|
WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
|
|
|
|
|
PF_PIPE_SEL_IVB(crtc->pipe));
|
|
|
|
|
}
|
2013-05-07 23:34:16 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-20 12:51:52 +00:00
|
|
|
static void
|
|
|
|
|
ironlake_get_initial_plane_config(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_initial_plane_config *plane_config)
|
2014-03-07 08:57:50 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 val, base, offset;
|
2015-01-20 12:51:47 +00:00
|
|
|
int pipe = crtc->pipe;
|
2014-03-07 08:57:50 -08:00
|
|
|
int fourcc, pixel_format;
|
2015-03-23 11:10:32 +00:00
|
|
|
unsigned int aligned_height;
|
2015-01-20 12:51:46 +00:00
|
|
|
struct drm_framebuffer *fb;
|
2015-01-21 13:50:54 +00:00
|
|
|
struct intel_framebuffer *intel_fb;
|
2014-03-07 08:57:50 -08:00
|
|
|
|
2015-02-05 19:35:13 +00:00
|
|
|
val = I915_READ(DSPCNTR(pipe));
|
|
|
|
|
if (!(val & DISPLAY_PLANE_ENABLE))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-01-21 14:07:19 +00:00
|
|
|
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
|
2015-01-21 13:50:54 +00:00
|
|
|
if (!intel_fb) {
|
2014-03-07 08:57:50 -08:00
|
|
|
DRM_DEBUG_KMS("failed to alloc fb\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 13:50:54 +00:00
|
|
|
fb = &intel_fb->base;
|
|
|
|
|
|
2015-02-10 17:16:09 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
if (val & DISPPLANE_TILED) {
|
2015-01-20 12:51:44 +00:00
|
|
|
plane_config->tiling = I915_TILING_X;
|
2015-02-10 17:16:09 +00:00
|
|
|
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-07 08:57:50 -08:00
|
|
|
|
|
|
|
|
pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
|
2015-01-20 12:51:50 +00:00
|
|
|
fourcc = i9xx_format_to_fourcc(pixel_format);
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->pixel_format = fourcc;
|
|
|
|
|
fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
|
2014-03-07 08:57:50 -08:00
|
|
|
|
2015-01-20 12:51:47 +00:00
|
|
|
base = I915_READ(DSPSURF(pipe)) & 0xfffff000;
|
2014-03-07 08:57:50 -08:00
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
2015-01-20 12:51:47 +00:00
|
|
|
offset = I915_READ(DSPOFFSET(pipe));
|
2014-03-07 08:57:50 -08:00
|
|
|
} else {
|
2015-01-20 12:51:44 +00:00
|
|
|
if (plane_config->tiling)
|
2015-01-20 12:51:47 +00:00
|
|
|
offset = I915_READ(DSPTILEOFF(pipe));
|
2014-03-07 08:57:50 -08:00
|
|
|
else
|
2015-01-20 12:51:47 +00:00
|
|
|
offset = I915_READ(DSPLINOFF(pipe));
|
2014-03-07 08:57:50 -08:00
|
|
|
}
|
|
|
|
|
plane_config->base = base;
|
|
|
|
|
|
|
|
|
|
val = I915_READ(PIPESRC(pipe));
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->width = ((val >> 16) & 0xfff) + 1;
|
|
|
|
|
fb->height = ((val >> 0) & 0xfff) + 1;
|
2014-03-07 08:57:50 -08:00
|
|
|
|
|
|
|
|
val = I915_READ(DSPSTRIDE(pipe));
|
2015-01-20 12:51:46 +00:00
|
|
|
fb->pitches[0] = val & 0xffffffc0;
|
2014-03-07 08:57:50 -08:00
|
|
|
|
2015-01-20 12:51:46 +00:00
|
|
|
aligned_height = intel_fb_align_height(dev, fb->height,
|
2015-02-10 17:16:10 +00:00
|
|
|
fb->pixel_format,
|
|
|
|
|
fb->modifier[0]);
|
2014-03-07 08:57:50 -08:00
|
|
|
|
2015-02-10 23:12:27 +01:00
|
|
|
plane_config->size = fb->pitches[0] * aligned_height;
|
2014-03-07 08:57:50 -08:00
|
|
|
|
2015-01-20 12:51:48 +00:00
|
|
|
DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
|
|
|
|
|
pipe_name(pipe), fb->width, fb->height,
|
|
|
|
|
fb->bits_per_pixel, base, fb->pitches[0],
|
|
|
|
|
plane_config->size);
|
2015-01-20 12:51:46 +00:00
|
|
|
|
2015-02-05 17:22:18 +00:00
|
|
|
plane_config->fb = intel_fb;
|
2014-03-07 08:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-03-28 10:42:00 +01:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv,
|
|
|
|
|
POWER_DOMAIN_PIPE(crtc->pipe)))
|
2014-07-04 13:38:34 -03:00
|
|
|
return false;
|
|
|
|
|
|
2013-07-04 12:01:15 +02:00
|
|
|
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
|
2013-06-07 23:11:08 +02:00
|
|
|
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
|
2013-05-22 00:50:22 +02:00
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
tmp = I915_READ(PIPECONF(crtc->pipe));
|
|
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-09-06 23:29:00 +03:00
|
|
|
switch (tmp & PIPECONF_BPC_MASK) {
|
|
|
|
|
case PIPECONF_6BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 18;
|
|
|
|
|
break;
|
|
|
|
|
case PIPECONF_8BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 24;
|
|
|
|
|
break;
|
|
|
|
|
case PIPECONF_10BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 30;
|
|
|
|
|
break;
|
|
|
|
|
case PIPECONF_12BPC:
|
|
|
|
|
pipe_config->pipe_bpp = 36;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-24 23:54:49 +02:00
|
|
|
if (tmp & PIPECONF_COLOR_RANGE_SELECT)
|
|
|
|
|
pipe_config->limited_color_range = true;
|
|
|
|
|
|
2013-05-03 11:49:46 +02:00
|
|
|
if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
|
2013-06-05 13:34:20 +02:00
|
|
|
struct intel_shared_dpll *pll;
|
|
|
|
|
|
2013-03-28 10:42:01 +01:00
|
|
|
pipe_config->has_pch_encoder = true;
|
|
|
|
|
|
2013-04-29 19:33:42 +02: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 13:28:53 +02:00
|
|
|
|
|
|
|
|
ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
2013-06-06 12:45:25 +02:00
|
|
|
|
2013-06-07 23:11:08 +02:00
|
|
|
if (HAS_PCH_IBX(dev_priv->dev)) {
|
2013-07-04 12:01:16 +02:00
|
|
|
pipe_config->shared_dpll =
|
|
|
|
|
(enum intel_dpll_id) crtc->pipe;
|
2013-06-07 23:11:08 +02:00
|
|
|
} else {
|
|
|
|
|
tmp = I915_READ(PCH_DPLL_SEL);
|
|
|
|
|
if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B;
|
|
|
|
|
else
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A;
|
|
|
|
|
}
|
2013-06-05 13:34:20 +02:00
|
|
|
|
|
|
|
|
pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
|
|
|
|
|
|
|
|
|
|
WARN_ON(!pll->get_hw_state(dev_priv, pll,
|
|
|
|
|
&pipe_config->dpll_hw_state));
|
2013-06-27 19:47:19 +02:00
|
|
|
|
|
|
|
|
tmp = pipe_config->dpll_hw_state.dpll;
|
|
|
|
|
pipe_config->pixel_multiplier =
|
|
|
|
|
((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK)
|
|
|
|
|
>> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1;
|
2013-09-13 16:00:08 +03:00
|
|
|
|
|
|
|
|
ironlake_pch_clock_get(crtc, pipe_config);
|
2013-06-06 12:45:25 +02:00
|
|
|
} else {
|
|
|
|
|
pipe_config->pixel_multiplier = 1;
|
2013-04-29 19:33:42 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-29 21:56:12 +02:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
ironlake_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-23 11:19:26 -03:00
|
|
|
static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc)
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n",
|
2013-07-23 11:19:26 -03:00
|
|
|
pipe_name(crtc->pipe));
|
|
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
|
|
|
|
|
I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
|
2015-09-18 20:03:33 +03:00
|
|
|
I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
|
|
|
|
|
I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
|
|
|
|
|
I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
|
2013-07-23 11:19:26 -03:00
|
|
|
"CPU PWM1 enabled\n");
|
2014-07-04 11:50:30 -03:00
|
|
|
if (IS_HASWELL(dev))
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
|
2014-07-04 11:50:30 -03:00
|
|
|
"CPU PWM2 enabled\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
|
2013-07-23 11:19:26 -03:00
|
|
|
"PCH PWM1 enabled\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
|
2013-07-23 11:19:26 -03:00
|
|
|
"Utility pin enabled\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n");
|
2013-07-23 11:19:26 -03:00
|
|
|
|
2014-04-01 19:39:47 -03:00
|
|
|
/*
|
|
|
|
|
* In theory we can still leave IRQs enabled, as long as only the HPD
|
|
|
|
|
* interrupts remain enabled. We used to check for that, but since it's
|
|
|
|
|
* gen-specific and since we only disable LCPLL after we fully disable
|
|
|
|
|
* the interrupts, the check below should be enough.
|
|
|
|
|
*/
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
|
2013-07-23 11:19:26 -03:00
|
|
|
}
|
|
|
|
|
|
2014-07-04 11:59:58 -03:00
|
|
|
static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
|
|
|
|
|
if (IS_HASWELL(dev))
|
|
|
|
|
return I915_READ(D_COMP_HSW);
|
|
|
|
|
else
|
|
|
|
|
return I915_READ(D_COMP_BDW);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-07 20:12:36 -03:00
|
|
|
static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
|
|
|
|
|
if (IS_HASWELL(dev)) {
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
|
|
|
|
|
val))
|
2014-07-04 11:59:57 -03:00
|
|
|
DRM_ERROR("Failed to write to D_COMP\n");
|
2014-03-07 20:12:36 -03:00
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
} else {
|
2014-07-04 11:59:58 -03:00
|
|
|
I915_WRITE(D_COMP_BDW, val);
|
|
|
|
|
POSTING_READ(D_COMP_BDW);
|
2014-03-07 20:12:36 -03:00
|
|
|
}
|
2013-07-23 11:19:26 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function implements pieces of two sequences from BSpec:
|
|
|
|
|
* - Sequence for display software to disable LCPLL
|
|
|
|
|
* - Sequence for display software to allow package C8+
|
|
|
|
|
* The steps implemented here are just the steps that actually touch the LCPLL
|
|
|
|
|
* register. Callers should take care of disabling all the display engine
|
|
|
|
|
* functions, doing the mode unset, fixing interrupts, etc.
|
|
|
|
|
*/
|
2013-09-24 13:52:57 -03:00
|
|
|
static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
|
|
|
|
|
bool switch_to_fclk, bool allow_power_down)
|
2013-07-23 11:19:26 -03:00
|
|
|
{
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
assert_can_disable_lcpll(dev_priv);
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
|
|
|
|
|
if (switch_to_fclk) {
|
|
|
|
|
val |= LCPLL_CD_SOURCE_FCLK;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
|
|
|
|
|
LCPLL_CD_SOURCE_FCLK_DONE, 1))
|
|
|
|
|
DRM_ERROR("Switching to FCLK failed\n");
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val |= LCPLL_PLL_DISABLE;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
POSTING_READ(LCPLL_CTL);
|
|
|
|
|
|
|
|
|
|
if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1))
|
|
|
|
|
DRM_ERROR("LCPLL still locked\n");
|
|
|
|
|
|
2014-07-04 11:59:58 -03:00
|
|
|
val = hsw_read_dcomp(dev_priv);
|
2013-07-23 11:19:26 -03:00
|
|
|
val |= D_COMP_COMP_DISABLE;
|
2014-03-07 20:12:36 -03:00
|
|
|
hsw_write_dcomp(dev_priv, val);
|
2013-07-23 11:19:26 -03:00
|
|
|
ndelay(100);
|
|
|
|
|
|
2014-07-04 11:59:58 -03:00
|
|
|
if (wait_for((hsw_read_dcomp(dev_priv) & D_COMP_RCOMP_IN_PROGRESS) == 0,
|
|
|
|
|
1))
|
2013-07-23 11:19:26 -03:00
|
|
|
DRM_ERROR("D_COMP RCOMP still in progress\n");
|
|
|
|
|
|
|
|
|
|
if (allow_power_down) {
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val |= LCPLL_POWER_DOWN_ALLOW;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
POSTING_READ(LCPLL_CTL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Fully restores LCPLL, disallowing power down and switching back to LCPLL
|
|
|
|
|
* source.
|
|
|
|
|
*/
|
2013-09-24 13:52:57 -03:00
|
|
|
static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
|
2013-07-23 11:19:26 -03:00
|
|
|
{
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
|
|
|
|
|
if ((val & (LCPLL_PLL_LOCK | LCPLL_PLL_DISABLE | LCPLL_CD_SOURCE_FCLK |
|
|
|
|
|
LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK)
|
|
|
|
|
return;
|
|
|
|
|
|
drm/i915: make PC8 be part of runtime PM suspend/resume
Currently, when our driver becomes idle for i915.pc8_timeout (default:
5s) we enable PC8, so we save some power, but not everything we can.
Then, while PC8 is enabled, if we stay idle for more
autosuspend_delay_ms (default: 10s) we'll enter runtime PM and put the
graphics device in D3 state, saving even more power. The two features
are separate things with increasing levels of power savings, but if we
disable PC8 we'll never get into D3.
While from the modularity point of view it would be nice to keep these
features as separate, we have reasons to merge them:
- We are not aware of anybody wanting a "PC8 without D3" environment.
- If we keep both features as separate, we'll have to to test both
PC8 and PC8+D3 code paths. We're already having a major pain to
make QA do automated testing of just one thing, testing both paths
will cost even more.
- Only Haswell+ supports PC8, so if we want to add runtime PM support
to, for example, IVB, we'll have to copy some code from the PC8
feature to runtime PM, so merging both features as a single thing
will make it easier for enabling runtime PM on other platforms.
This patch only does the very basic steps required to have PC8 and
runtime PM merged on a single feature: the next patches will take care
of cleaning up everything.
v2: - Rebase.
v3: - Rebase.
- Fully remove the deprecated i915 params since Daniel doesn't
consider them as part of the ABI.
v4: - Rebase.
- Fix typo in the commit message.
v5: - Rebase, again.
- Add a huge comment explaining the different forcewake usage
(Chris, Daniel).
- Use open-coded forcewake functions (Daniel).
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>
2014-03-07 20:08:05 -03:00
|
|
|
/*
|
|
|
|
|
* Make sure we're not on PC8 state before disabling PC8, otherwise
|
|
|
|
|
* we'll hang the machine. To prevent PC8 state, just enable force_wake.
|
|
|
|
|
*/
|
2015-01-16 11:34:40 +02:00
|
|
|
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
|
2013-08-19 13:18:07 -03:00
|
|
|
|
2013-07-23 11:19:26 -03:00
|
|
|
if (val & LCPLL_POWER_DOWN_ALLOW) {
|
|
|
|
|
val &= ~LCPLL_POWER_DOWN_ALLOW;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
2013-08-21 23:38:08 +02:00
|
|
|
POSTING_READ(LCPLL_CTL);
|
2013-07-23 11:19:26 -03:00
|
|
|
}
|
|
|
|
|
|
2014-07-04 11:59:58 -03:00
|
|
|
val = hsw_read_dcomp(dev_priv);
|
2013-07-23 11:19:26 -03:00
|
|
|
val |= D_COMP_COMP_FORCE;
|
|
|
|
|
val &= ~D_COMP_COMP_DISABLE;
|
2014-03-07 20:12:36 -03:00
|
|
|
hsw_write_dcomp(dev_priv, val);
|
2013-07-23 11:19:26 -03:00
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val &= ~LCPLL_PLL_DISABLE;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
if (wait_for(I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK, 5))
|
|
|
|
|
DRM_ERROR("LCPLL not locked yet\n");
|
|
|
|
|
|
|
|
|
|
if (val & LCPLL_CD_SOURCE_FCLK) {
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val &= ~LCPLL_CD_SOURCE_FCLK;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
|
|
|
|
|
LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
|
|
|
|
DRM_ERROR("Switching back to LCPLL failed\n");
|
|
|
|
|
}
|
2013-08-19 13:18:07 -03:00
|
|
|
|
2015-01-16 11:34:40 +02:00
|
|
|
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
|
2015-06-03 15:45:07 +03:00
|
|
|
intel_update_cdclk(dev_priv->dev);
|
2013-07-23 11:19:26 -03:00
|
|
|
}
|
|
|
|
|
|
2014-03-07 20:08:18 -03:00
|
|
|
/*
|
|
|
|
|
* Package states C8 and deeper are really deep PC states that can only be
|
|
|
|
|
* reached when all the devices on the system allow it, so even if the graphics
|
|
|
|
|
* device allows PC8+, it doesn't mean the system will actually get to these
|
|
|
|
|
* states. Our driver only allows PC8+ when going into runtime PM.
|
|
|
|
|
*
|
|
|
|
|
* The requirements for PC8+ are that all the outputs are disabled, the power
|
|
|
|
|
* well is disabled and most interrupts are disabled, and these are also
|
|
|
|
|
* requirements for runtime PM. When these conditions are met, we manually do
|
|
|
|
|
* the other conditions: disable the interrupts, clocks and switch LCPLL refclk
|
|
|
|
|
* to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard
|
|
|
|
|
* hang the machine.
|
|
|
|
|
*
|
|
|
|
|
* When we really reach PC8 or deeper states (not just when we allow it) we lose
|
|
|
|
|
* the state of some registers, so when we come back from PC8+ we need to
|
|
|
|
|
* restore this state. We don't get into PC8+ if we're not in RC6, so we don't
|
|
|
|
|
* need to take care of the registers kept by RC6. Notice that this happens even
|
|
|
|
|
* if we don't put the device in PCI D3 state (which is what currently happens
|
|
|
|
|
* because of the runtime PM support).
|
|
|
|
|
*
|
|
|
|
|
* For more, read "Display Sequences for Package C8" on the hardware
|
|
|
|
|
* documentation.
|
|
|
|
|
*/
|
2014-03-07 20:08:17 -03:00
|
|
|
void hsw_enable_pc8(struct drm_i915_private *dev_priv)
|
2013-08-19 13:18:09 -03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Enabling package C8+\n");
|
|
|
|
|
|
2015-08-27 23:55:59 +03:00
|
|
|
if (HAS_PCH_LPT_LP(dev)) {
|
2013-08-19 13:18:09 -03:00
|
|
|
val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
|
|
val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
|
|
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lpt_disable_clkout_dp(dev);
|
|
|
|
|
hsw_disable_lcpll(dev_priv, true, true);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-07 20:08:17 -03:00
|
|
|
void hsw_disable_pc8(struct drm_i915_private *dev_priv)
|
2013-08-19 13:18:09 -03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("Disabling package C8+\n");
|
|
|
|
|
|
|
|
|
|
hsw_restore_lcpll(dev_priv);
|
|
|
|
|
lpt_init_pch_refclk(dev);
|
|
|
|
|
|
2015-08-27 23:55:59 +03:00
|
|
|
if (HAS_PCH_LPT_LP(dev)) {
|
2013-08-19 13:18:09 -03:00
|
|
|
val = I915_READ(SOUTH_DSPCLK_GATE_D);
|
|
|
|
|
val |= PCH_LP_PARTITION_LEVEL_DISABLE;
|
|
|
|
|
I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intel_prepare_ddi(dev);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
2014-11-24 13:37:39 +05:30
|
|
|
{
|
2015-04-21 17:13:23 +03:00
|
|
|
struct drm_device *dev = old_state->dev;
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *old_intel_state =
|
|
|
|
|
to_intel_atomic_state(old_state);
|
|
|
|
|
unsigned int req_cdclk = old_intel_state->dev_cdclk;
|
2014-11-24 13:37:39 +05:30
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
broxton_set_cdclk(dev, req_cdclk);
|
2014-11-24 13:37:39 +05:30
|
|
|
}
|
|
|
|
|
|
2015-06-03 15:45:13 +03:00
|
|
|
/* compute the max rate for new configuration */
|
2015-06-15 12:33:56 +02:00
|
|
|
static int ilk_max_pixel_rate(struct drm_atomic_state *state)
|
2015-06-03 15:45:13 +03:00
|
|
|
{
|
2015-12-10 12:33:57 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
|
|
struct drm_i915_private *dev_priv = state->dev->dev_private;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *cstate;
|
2015-06-15 12:33:56 +02:00
|
|
|
struct intel_crtc_state *crtc_state;
|
2015-12-10 12:33:57 +01:00
|
|
|
unsigned max_pixel_rate = 0, i;
|
|
|
|
|
enum pipe pipe;
|
2015-06-03 15:45:13 +03:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
|
|
|
|
|
sizeof(intel_state->min_pixclk));
|
2015-06-15 12:33:56 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
for_each_crtc_in_state(state, crtc, cstate, i) {
|
|
|
|
|
int pixel_rate;
|
2015-06-15 12:33:56 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
crtc_state = to_intel_crtc_state(cstate);
|
|
|
|
|
if (!crtc_state->base.enable) {
|
|
|
|
|
intel_state->min_pixclk[i] = 0;
|
2015-06-03 15:45:13 +03:00
|
|
|
continue;
|
2015-12-10 12:33:57 +01:00
|
|
|
}
|
2015-06-03 15:45:13 +03:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
pixel_rate = ilk_pipe_pixel_rate(crtc_state);
|
2015-06-03 15:45:13 +03:00
|
|
|
|
|
|
|
|
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
|
2015-12-10 12:33:57 +01:00
|
|
|
if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
|
2015-06-03 15:45:13 +03:00
|
|
|
pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
|
|
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
intel_state->min_pixclk[i] = pixel_rate;
|
2015-06-03 15:45:13 +03:00
|
|
|
}
|
|
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (!intel_state->active_crtcs)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for_each_pipe(dev_priv, pipe)
|
|
|
|
|
max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
|
|
|
|
|
|
2015-06-03 15:45:13 +03:00
|
|
|
return max_pixel_rate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
uint32_t val, data;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (WARN((I915_READ(LCPLL_CTL) &
|
|
|
|
|
(LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
|
|
|
|
|
LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
|
|
|
|
|
LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
|
|
|
|
|
LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
|
|
|
|
|
"trying to change cdclk frequency with cdclk not enabled\n"))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
ret = sandybridge_pcode_write(dev_priv,
|
|
|
|
|
BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
if (ret) {
|
|
|
|
|
DRM_ERROR("failed to inform pcode about cdclk change\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val |= LCPLL_CD_SOURCE_FCLK;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
|
|
|
|
|
LCPLL_CD_SOURCE_FCLK_DONE, 1))
|
|
|
|
|
DRM_ERROR("Switching to FCLK failed\n");
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val &= ~LCPLL_CLK_FREQ_MASK;
|
|
|
|
|
|
|
|
|
|
switch (cdclk) {
|
|
|
|
|
case 450000:
|
|
|
|
|
val |= LCPLL_CLK_FREQ_450;
|
|
|
|
|
data = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 540000:
|
|
|
|
|
val |= LCPLL_CLK_FREQ_54O_BDW;
|
|
|
|
|
data = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 337500:
|
|
|
|
|
val |= LCPLL_CLK_FREQ_337_5_BDW;
|
|
|
|
|
data = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 675000:
|
|
|
|
|
val |= LCPLL_CLK_FREQ_675_BDW;
|
|
|
|
|
data = 3;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
WARN(1, "invalid cdclk frequency\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
val = I915_READ(LCPLL_CTL);
|
|
|
|
|
val &= ~LCPLL_CD_SOURCE_FCLK;
|
|
|
|
|
I915_WRITE(LCPLL_CTL, val);
|
|
|
|
|
|
|
|
|
|
if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
|
|
|
|
|
LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
|
|
|
|
DRM_ERROR("Switching back to LCPLL failed\n");
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
intel_update_cdclk(dev);
|
|
|
|
|
|
|
|
|
|
WARN(cdclk != dev_priv->cdclk_freq,
|
|
|
|
|
"cdclk requested %d kHz but got %d kHz\n",
|
|
|
|
|
cdclk, dev_priv->cdclk_freq);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
|
2015-06-03 15:45:13 +03:00
|
|
|
{
|
2015-06-15 12:33:56 +02:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
2015-06-15 12:33:56 +02:00
|
|
|
int max_pixclk = ilk_max_pixel_rate(state);
|
2015-06-03 15:45:13 +03:00
|
|
|
int cdclk;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME should also account for plane ratio
|
|
|
|
|
* once 64bpp pixel formats are supported.
|
|
|
|
|
*/
|
2015-06-15 12:33:56 +02:00
|
|
|
if (max_pixclk > 540000)
|
2015-06-03 15:45:13 +03:00
|
|
|
cdclk = 675000;
|
2015-06-15 12:33:56 +02:00
|
|
|
else if (max_pixclk > 450000)
|
2015-06-03 15:45:13 +03:00
|
|
|
cdclk = 540000;
|
2015-06-15 12:33:56 +02:00
|
|
|
else if (max_pixclk > 337500)
|
2015-06-03 15:45:13 +03:00
|
|
|
cdclk = 450000;
|
|
|
|
|
else
|
|
|
|
|
cdclk = 337500;
|
|
|
|
|
|
|
|
|
|
if (cdclk > dev_priv->max_cdclk_freq) {
|
2015-11-24 11:29:03 +01:00
|
|
|
DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
|
|
|
|
|
cdclk, dev_priv->max_cdclk_freq);
|
|
|
|
|
return -EINVAL;
|
2015-06-03 15:45:13 +03:00
|
|
|
}
|
|
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
intel_state->cdclk = intel_state->dev_cdclk = cdclk;
|
|
|
|
|
if (!intel_state->active_crtcs)
|
|
|
|
|
intel_state->dev_cdclk = 337500;
|
2015-06-03 15:45:13 +03:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
|
2015-06-03 15:45:13 +03:00
|
|
|
{
|
2015-06-15 12:33:56 +02:00
|
|
|
struct drm_device *dev = old_state->dev;
|
2015-12-03 14:31:06 +01:00
|
|
|
struct intel_atomic_state *old_intel_state =
|
|
|
|
|
to_intel_atomic_state(old_state);
|
|
|
|
|
unsigned req_cdclk = old_intel_state->dev_cdclk;
|
2015-06-03 15:45:13 +03:00
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
broadwell_set_cdclk(dev, req_cdclk);
|
2015-06-03 15:45:13 +03:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:23 +02:00
|
|
|
static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state)
|
2012-10-05 12:05:55 -03:00
|
|
|
{
|
2015-01-15 14:55:23 +02:00
|
|
|
if (!intel_ddi_pll_select(crtc, crtc_state))
|
2012-10-05 12:05:58 -03:00
|
|
|
return -EINVAL;
|
2014-06-25 22:02:02 +03:00
|
|
|
|
2014-10-20 13:46:44 +03:00
|
|
|
crtc->lowfreq_avail = false;
|
2014-04-24 23:55:07 +02:00
|
|
|
|
2014-04-24 23:55:04 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2014-08-22 09:49:11 +05:30
|
|
|
static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum port port,
|
|
|
|
|
struct intel_crtc_state *pipe_config)
|
|
|
|
|
{
|
|
|
|
|
switch (port) {
|
|
|
|
|
case PORT_A:
|
|
|
|
|
pipe_config->ddi_pll_sel = SKL_DPLL0;
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
|
|
|
|
|
break;
|
|
|
|
|
case PORT_B:
|
|
|
|
|
pipe_config->ddi_pll_sel = SKL_DPLL1;
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
|
|
|
|
|
break;
|
|
|
|
|
case PORT_C:
|
|
|
|
|
pipe_config->ddi_pll_sel = SKL_DPLL2;
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
DRM_ERROR("Incorrect port type\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-13 14:55:17 +00:00
|
|
|
static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum port port,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-11-13 14:55:17 +00:00
|
|
|
{
|
2014-11-21 16:14:56 +00:00
|
|
|
u32 temp, dpll_ctl1;
|
2014-11-13 14:55:17 +00:00
|
|
|
|
|
|
|
|
temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port);
|
|
|
|
|
pipe_config->ddi_pll_sel = temp >> (port * 3 + 1);
|
|
|
|
|
|
|
|
|
|
switch (pipe_config->ddi_pll_sel) {
|
2014-11-21 16:14:56 +00:00
|
|
|
case SKL_DPLL0:
|
|
|
|
|
/*
|
|
|
|
|
* On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part
|
|
|
|
|
* of the shared DPLL framework and thus needs to be read out
|
|
|
|
|
* separately
|
|
|
|
|
*/
|
|
|
|
|
dpll_ctl1 = I915_READ(DPLL_CTRL1);
|
|
|
|
|
pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f;
|
|
|
|
|
break;
|
2014-11-13 14:55:17 +00:00
|
|
|
case SKL_DPLL1:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
|
|
|
|
|
break;
|
|
|
|
|
case SKL_DPLL2:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
|
|
|
|
|
break;
|
|
|
|
|
case SKL_DPLL3:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 18:06:18 +01:00
|
|
|
static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|
|
|
|
enum port port,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-07-29 18:06:18 +01:00
|
|
|
{
|
|
|
|
|
pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
|
|
|
|
|
|
|
|
|
|
switch (pipe_config->ddi_pll_sel) {
|
|
|
|
|
case PORT_CLK_SEL_WRPLL1:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_WRPLL1;
|
|
|
|
|
break;
|
|
|
|
|
case PORT_CLK_SEL_WRPLL2:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
|
|
|
|
|
break;
|
2015-11-16 14:42:12 +01:00
|
|
|
case PORT_CLK_SEL_SPLL:
|
|
|
|
|
pipe_config->shared_dpll = DPLL_ID_SPLL;
|
2015-12-01 23:32:07 +02:00
|
|
|
break;
|
2014-07-29 18:06:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 22:01:55 +03:00
|
|
|
static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2014-06-25 22:01:55 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-07-04 11:27:39 -03:00
|
|
|
struct intel_shared_dpll *pll;
|
2014-06-25 22:01:55 +03:00
|
|
|
enum port port;
|
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
|
|
tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
|
|
|
|
|
|
|
|
|
|
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
|
|
|
|
|
|
2015-10-28 04:16:45 -07:00
|
|
|
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
2014-11-13 14:55:17 +00:00
|
|
|
skylake_get_ddi_pll(dev_priv, port, pipe_config);
|
2014-08-22 09:49:11 +05:30
|
|
|
else if (IS_BROXTON(dev))
|
|
|
|
|
bxt_get_ddi_pll(dev_priv, port, pipe_config);
|
2014-11-13 14:55:17 +00:00
|
|
|
else
|
|
|
|
|
haswell_get_ddi_pll(dev_priv, port, pipe_config);
|
2014-06-25 22:01:57 +03:00
|
|
|
|
2014-07-04 11:27:39 -03:00
|
|
|
if (pipe_config->shared_dpll >= 0) {
|
|
|
|
|
pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
|
|
|
|
|
|
|
|
|
|
WARN_ON(!pll->get_hw_state(dev_priv, pll,
|
|
|
|
|
&pipe_config->dpll_hw_state));
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 22:01:55 +03:00
|
|
|
/*
|
|
|
|
|
* Haswell has only FDI/PCH transcoder A. It is which is connected to
|
|
|
|
|
* DDI E. So just check whether this pipe is wired to DDI E and whether
|
|
|
|
|
* the PCH transcoder is on.
|
|
|
|
|
*/
|
2013-12-03 13:56:24 +00:00
|
|
|
if (INTEL_INFO(dev)->gen < 9 &&
|
|
|
|
|
(port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
|
2014-06-25 22:01:55 +03:00
|
|
|
pipe_config->has_pch_encoder = true;
|
|
|
|
|
|
|
|
|
|
tmp = I915_READ(FDI_RX_CTL(PIPE_A));
|
|
|
|
|
pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
|
|
|
|
|
FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
|
|
|
|
|
|
|
|
|
ironlake_get_fdi_m_n_config(crtc, pipe_config);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-03-28 10:42:00 +01:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-05-07 23:34:16 +02:00
|
|
|
enum intel_display_power_domain pfit_domain;
|
2013-03-28 10:42:00 +01:00
|
|
|
uint32_t tmp;
|
|
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv,
|
2014-03-05 16:20:55 +02:00
|
|
|
POWER_DOMAIN_PIPE(crtc->pipe)))
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-07-04 12:01:15 +02:00
|
|
|
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
|
2013-06-07 23:11:08 +02:00
|
|
|
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
|
|
|
|
|
|
2013-05-22 00:50:22 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv,
|
2013-05-22 00:50:22 +02:00
|
|
|
POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
|
2013-04-18 16:35:40 -03:00
|
|
|
return false;
|
|
|
|
|
|
2013-05-22 00:50:22 +02:00
|
|
|
tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
|
2013-03-28 10:42:00 +01:00
|
|
|
if (!(tmp & PIPECONF_ENABLE))
|
|
|
|
|
return false;
|
|
|
|
|
|
2014-06-25 22:01:55 +03:00
|
|
|
haswell_get_ddi_port_state(crtc, pipe_config);
|
2013-04-29 19:33:42 +02:00
|
|
|
|
2013-04-29 21:56:12 +02:00
|
|
|
intel_get_pipe_timings(crtc, pipe_config);
|
|
|
|
|
|
2015-04-07 15:28:45 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
skl_init_scalers(dev, crtc, pipe_config);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-07 23:34:16 +02:00
|
|
|
pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
|
2015-05-11 14:35:47 -07:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
pipe_config->scaler_state.scaler_id = -1;
|
|
|
|
|
pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-13 17:51:47 +00:00
|
|
|
if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
|
2015-09-02 15:19:26 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
2014-11-13 17:51:47 +00:00
|
|
|
skylake_get_pfit_config(crtc, pipe_config);
|
2015-01-21 17:19:54 -08:00
|
|
|
else
|
2015-09-02 15:19:26 -07:00
|
|
|
ironlake_get_pfit_config(crtc, pipe_config);
|
2014-11-13 17:51:47 +00:00
|
|
|
}
|
2013-03-28 10:42:01 +01:00
|
|
|
|
2014-01-07 13:30:45 -08:00
|
|
|
if (IS_HASWELL(dev))
|
|
|
|
|
pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
|
|
|
|
|
(I915_READ(IPS_CTL) & IPS_ENABLE);
|
2013-05-31 16:33:22 -03:00
|
|
|
|
2014-09-30 10:30:22 -07:00
|
|
|
if (pipe_config->cpu_transcoder != TRANSCODER_EDP) {
|
|
|
|
|
pipe_config->pixel_multiplier =
|
|
|
|
|
I915_READ(PIPE_MULT(pipe_config->cpu_transcoder)) + 1;
|
|
|
|
|
} else {
|
|
|
|
|
pipe_config->pixel_multiplier = 1;
|
|
|
|
|
}
|
2013-06-06 12:45:25 +02:00
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
|
|
|
|
|
const struct intel_plane_state *plane_state)
|
2010-08-07 11:01:38 +01: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);
|
2014-08-13 11:57:05 +03:00
|
|
|
uint32_t cntl = 0, size = 0;
|
2010-08-07 11:01:38 +01:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (plane_state && plane_state->visible) {
|
|
|
|
|
unsigned int width = plane_state->base.crtc_w;
|
|
|
|
|
unsigned int height = plane_state->base.crtc_h;
|
2014-08-13 11:57:05 +03:00
|
|
|
unsigned int stride = roundup_pow_of_two(width) * 4;
|
|
|
|
|
|
|
|
|
|
switch (stride) {
|
|
|
|
|
default:
|
|
|
|
|
WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n",
|
|
|
|
|
width, stride);
|
|
|
|
|
stride = 256;
|
|
|
|
|
/* fallthrough */
|
|
|
|
|
case 256:
|
|
|
|
|
case 512:
|
|
|
|
|
case 1024:
|
|
|
|
|
case 2048:
|
|
|
|
|
break;
|
2014-05-30 16:35:26 +03:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 11:57:05 +03:00
|
|
|
cntl |= CURSOR_ENABLE |
|
|
|
|
|
CURSOR_GAMMA_ENABLE |
|
|
|
|
|
CURSOR_FORMAT_ARGB |
|
|
|
|
|
CURSOR_STRIDE(stride);
|
|
|
|
|
|
|
|
|
|
size = (height << 12) | width;
|
2014-05-30 16:35:26 +03:00
|
|
|
}
|
2010-08-07 11:01:38 +01:00
|
|
|
|
2014-08-13 11:57:05 +03:00
|
|
|
if (intel_crtc->cursor_cntl != 0 &&
|
|
|
|
|
(intel_crtc->cursor_base != base ||
|
|
|
|
|
intel_crtc->cursor_size != size ||
|
|
|
|
|
intel_crtc->cursor_cntl != cntl)) {
|
|
|
|
|
/* On these chipsets we can only modify the base/size/stride
|
|
|
|
|
* whilst the cursor is disabled.
|
|
|
|
|
*/
|
2015-09-22 19:47:51 +03:00
|
|
|
I915_WRITE(CURCNTR(PIPE_A), 0);
|
|
|
|
|
POSTING_READ(CURCNTR(PIPE_A));
|
2014-08-13 11:57:05 +03:00
|
|
|
intel_crtc->cursor_cntl = 0;
|
2014-05-30 16:35:26 +03:00
|
|
|
}
|
2010-08-07 11:01:38 +01:00
|
|
|
|
2014-09-12 20:53:32 +03:00
|
|
|
if (intel_crtc->cursor_base != base) {
|
2015-09-22 19:47:51 +03:00
|
|
|
I915_WRITE(CURBASE(PIPE_A), base);
|
2014-09-12 20:53:32 +03:00
|
|
|
intel_crtc->cursor_base = base;
|
|
|
|
|
}
|
2014-03-10 17:06:23 +05:30
|
|
|
|
2014-08-13 11:57:05 +03:00
|
|
|
if (intel_crtc->cursor_size != size) {
|
|
|
|
|
I915_WRITE(CURSIZE, size);
|
|
|
|
|
intel_crtc->cursor_size = size;
|
2014-05-30 16:35:26 +03:00
|
|
|
}
|
2010-08-07 11:01:38 +01:00
|
|
|
|
2014-05-30 16:35:26 +03:00
|
|
|
if (intel_crtc->cursor_cntl != cntl) {
|
2015-09-22 19:47:51 +03:00
|
|
|
I915_WRITE(CURCNTR(PIPE_A), cntl);
|
|
|
|
|
POSTING_READ(CURCNTR(PIPE_A));
|
2014-05-30 16:35:26 +03:00
|
|
|
intel_crtc->cursor_cntl = cntl;
|
2010-08-07 11:01:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
|
|
|
|
|
const struct intel_plane_state *plane_state)
|
2011-10-12 11:10:21 -07: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;
|
2015-12-14 13:16:48 +02:00
|
|
|
uint32_t cntl = 0;
|
2014-05-30 16:35:26 +03:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (plane_state && plane_state->visible) {
|
2014-05-30 16:35:26 +03:00
|
|
|
cntl = MCURSOR_GAMMA_ENABLE;
|
2016-01-07 11:54:10 +01:00
|
|
|
switch (plane_state->base.crtc_w) {
|
2014-03-10 17:06:23 +05:30
|
|
|
case 64:
|
|
|
|
|
cntl |= CURSOR_MODE_64_ARGB_AX;
|
|
|
|
|
break;
|
|
|
|
|
case 128:
|
|
|
|
|
cntl |= CURSOR_MODE_128_ARGB_AX;
|
|
|
|
|
break;
|
|
|
|
|
case 256:
|
|
|
|
|
cntl |= CURSOR_MODE_256_ARGB_AX;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2016-01-07 11:54:10 +01:00
|
|
|
MISSING_CASE(plane_state->base.crtc_w);
|
2014-03-10 17:06:23 +05:30
|
|
|
return;
|
2011-10-12 11:10:21 -07:00
|
|
|
}
|
2014-05-30 16:35:26 +03:00
|
|
|
cntl |= pipe << 28; /* Connect to correct pipe */
|
2014-09-12 20:53:33 +03:00
|
|
|
|
2015-08-31 14:03:30 -07:00
|
|
|
if (HAS_DDI(dev))
|
2014-09-12 20:53:33 +03:00
|
|
|
cntl |= CURSOR_PIPE_CSC_ENABLE;
|
2011-10-12 11:10:21 -07:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (plane_state->base.rotation == BIT(DRM_ROTATE_180))
|
|
|
|
|
cntl |= CURSOR_ROTATE_180;
|
|
|
|
|
}
|
2014-10-23 07:41:34 -07:00
|
|
|
|
2014-05-30 16:35:26 +03:00
|
|
|
if (intel_crtc->cursor_cntl != cntl) {
|
|
|
|
|
I915_WRITE(CURCNTR(pipe), cntl);
|
|
|
|
|
POSTING_READ(CURCNTR(pipe));
|
|
|
|
|
intel_crtc->cursor_cntl = cntl;
|
2011-10-12 11:10:21 -07:00
|
|
|
}
|
2014-05-30 16:35:26 +03:00
|
|
|
|
2011-10-12 11:10:21 -07:00
|
|
|
/* and commit changes on next vblank */
|
2014-04-09 13:28:53 +03:00
|
|
|
I915_WRITE(CURBASE(pipe), base);
|
|
|
|
|
POSTING_READ(CURBASE(pipe));
|
2014-09-12 20:53:32 +03:00
|
|
|
|
|
|
|
|
intel_crtc->cursor_base = base;
|
2011-10-12 11:10:21 -07:00
|
|
|
}
|
|
|
|
|
|
2010-07-09 08:45:04 +01:00
|
|
|
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
|
2010-09-13 13:54:26 +01:00
|
|
|
static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
2016-01-07 11:54:10 +01:00
|
|
|
const struct intel_plane_state *plane_state)
|
2010-07-09 08:45:04 +01: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;
|
2016-01-07 11:54:10 +01:00
|
|
|
u32 base = intel_crtc->cursor_addr;
|
|
|
|
|
u32 pos = 0;
|
2010-07-09 08:45:04 +01:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (plane_state) {
|
|
|
|
|
int x = plane_state->base.crtc_x;
|
|
|
|
|
int y = plane_state->base.crtc_y;
|
2010-07-09 08:45:04 +01:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (x < 0) {
|
|
|
|
|
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
|
|
|
|
x = -x;
|
|
|
|
|
}
|
|
|
|
|
pos |= x << CURSOR_X_SHIFT;
|
2010-07-09 08:45:04 +01:00
|
|
|
|
2016-01-07 11:54:10 +01:00
|
|
|
if (y < 0) {
|
|
|
|
|
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
|
|
|
|
y = -y;
|
|
|
|
|
}
|
|
|
|
|
pos |= y << CURSOR_Y_SHIFT;
|
|
|
|
|
|
|
|
|
|
/* ILK+ do this automagically */
|
|
|
|
|
if (HAS_GMCH_DISPLAY(dev) &&
|
|
|
|
|
plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
|
|
|
|
|
base += (plane_state->base.crtc_h *
|
|
|
|
|
plane_state->base.crtc_w - 1) * 4;
|
|
|
|
|
}
|
2010-07-09 08:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
2014-04-09 13:28:53 +03:00
|
|
|
I915_WRITE(CURPOS(pipe), pos);
|
|
|
|
|
|
2014-08-12 19:39:54 +03:00
|
|
|
if (IS_845G(dev) || IS_I865G(dev))
|
2016-01-07 11:54:10 +01:00
|
|
|
i845_update_cursor(crtc, base, plane_state);
|
2014-04-09 13:28:53 +03:00
|
|
|
else
|
2016-01-07 11:54:10 +01:00
|
|
|
i9xx_update_cursor(crtc, base, plane_state);
|
2010-07-09 08:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 11:57:05 +03:00
|
|
|
static bool cursor_size_ok(struct drm_device *dev,
|
|
|
|
|
uint32_t width, uint32_t height)
|
|
|
|
|
{
|
|
|
|
|
if (width == 0 || height == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 845g/865g are special in that they are only limited by
|
|
|
|
|
* the width of their cursors, the height is arbitrary up to
|
|
|
|
|
* the precision of the register. Everything else requires
|
|
|
|
|
* square cursors, limited to a few power-of-two sizes.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_845G(dev) || IS_I865G(dev)) {
|
|
|
|
|
if ((width & 63) != 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (width > (IS_845G(dev) ? 64 : 512))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (height > 1023)
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
switch (width | height) {
|
|
|
|
|
case 256:
|
|
|
|
|
case 128:
|
|
|
|
|
if (IS_GEN2(dev))
|
|
|
|
|
return false;
|
|
|
|
|
case 64:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
2010-08-03 01:33:19 +01: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-07 14:24:08 -08:00
|
|
|
{
|
2010-08-03 01:33:19 +01: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-07 14:24:08 -08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
2010-08-03 01:33:19 +01: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-07 14: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),
|
|
|
|
|
};
|
|
|
|
|
|
2014-02-10 18:00:39 +01:00
|
|
|
struct drm_framebuffer *
|
|
|
|
|
__intel_framebuffer_create(struct drm_device *dev,
|
|
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
|
|
struct drm_i915_gem_object *obj)
|
2011-04-19 08:36:26 +01:00
|
|
|
{
|
|
|
|
|
struct intel_framebuffer *intel_fb;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
if (!intel_fb)
|
2011-04-19 08:36:26 +01:00
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
|
|
ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
|
2013-10-09 21:23:51 +02:00
|
|
|
if (ret)
|
|
|
|
|
goto err;
|
2011-04-19 08:36:26 +01:00
|
|
|
|
|
|
|
|
return &intel_fb->base;
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
|
2013-10-09 21:23:51 +02:00
|
|
|
err:
|
|
|
|
|
kfree(intel_fb);
|
|
|
|
|
return ERR_PTR(ret);
|
2011-04-19 08:36:26 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-02 21:18:00 +01:00
|
|
|
static struct drm_framebuffer *
|
2014-02-10 18:00:39 +01:00
|
|
|
intel_framebuffer_create(struct drm_device *dev,
|
|
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
|
{
|
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = i915_mutex_lock_interruptible(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
|
fb = __intel_framebuffer_create(dev, mode_cmd, obj);
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
|
|
return fb;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-19 08:36:26 +01:00
|
|
|
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);
|
2014-07-01 20:39:41 +02:00
|
|
|
return PAGE_ALIGN(pitch * mode->vdisplay);
|
2011-04-19 08:36:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
|
|
intel_framebuffer_create_for_mode(struct drm_device *dev,
|
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
|
int depth, int bpp)
|
|
|
|
|
{
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
struct drm_framebuffer *fb;
|
2011-04-19 08:36:26 +01:00
|
|
|
struct drm_i915_gem_object *obj;
|
2012-11-05 22:25:07 +00:00
|
|
|
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
2011-04-19 08:36:26 +01: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-14 14:51:28 -08:00
|
|
|
mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
|
|
|
|
|
bpp);
|
2012-02-23 15:33:40 +00:00
|
|
|
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
|
2011-04-19 08:36:26 +01:00
|
|
|
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
fb = intel_framebuffer_create(dev, &mode_cmd, obj);
|
|
|
|
|
if (IS_ERR(fb))
|
|
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
|
|
|
|
|
|
|
|
|
return fb;
|
2011-04-19 08:36:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct drm_framebuffer *
|
|
|
|
|
mode_fits_in_fbdev(struct drm_device *dev,
|
|
|
|
|
struct drm_display_mode *mode)
|
|
|
|
|
{
|
2015-08-10 13:34:08 +02:00
|
|
|
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
2011-04-19 08:36:26 +01:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct drm_i915_gem_object *obj;
|
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
|
2014-02-14 16:35:54 +01:00
|
|
|
if (!dev_priv->fbdev)
|
2011-04-19 08:36:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
2014-02-14 16:35:54 +01:00
|
|
|
if (!dev_priv->fbdev->fb)
|
2011-04-19 08:36:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
2014-02-14 16:35:54 +01:00
|
|
|
obj = dev_priv->fbdev->fb->obj;
|
|
|
|
|
BUG_ON(!obj);
|
|
|
|
|
|
2014-02-07 12:10:38 -08:00
|
|
|
fb = &dev_priv->fbdev->fb->base;
|
2011-12-20 00:06:49 +02:00
|
|
|
if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
|
|
|
|
|
fb->bits_per_pixel))
|
2011-04-19 08:36:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
2011-12-20 00:06:49 +02:00
|
|
|
if (obj->base.size < mode->vdisplay * fb->pitches[0])
|
2011-04-19 08:36:26 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return fb;
|
2013-10-09 09:18:51 +02:00
|
|
|
#else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
2011-04-19 08:36:26 +01:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:09 +03:00
|
|
|
static int intel_modeset_setup_plane_state(struct drm_atomic_state *state,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_display_mode *mode,
|
|
|
|
|
struct drm_framebuffer *fb,
|
|
|
|
|
int x, int y)
|
|
|
|
|
{
|
|
|
|
|
struct drm_plane_state *plane_state;
|
|
|
|
|
int hdisplay, vdisplay;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
plane_state = drm_atomic_get_plane_state(state, crtc->primary);
|
|
|
|
|
if (IS_ERR(plane_state))
|
|
|
|
|
return PTR_ERR(plane_state);
|
|
|
|
|
|
|
|
|
|
if (mode)
|
|
|
|
|
drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
|
|
|
|
|
else
|
|
|
|
|
hdisplay = vdisplay = 0;
|
|
|
|
|
|
|
|
|
|
ret = drm_atomic_set_crtc_for_plane(plane_state, fb ? crtc : NULL);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
drm_atomic_set_fb_for_plane(plane_state, fb);
|
|
|
|
|
plane_state->crtc_x = 0;
|
|
|
|
|
plane_state->crtc_y = 0;
|
|
|
|
|
plane_state->crtc_w = hdisplay;
|
|
|
|
|
plane_state->crtc_h = vdisplay;
|
|
|
|
|
plane_state->src_x = x << 16;
|
|
|
|
|
plane_state->src_y = y << 16;
|
|
|
|
|
plane_state->src_w = hdisplay << 16;
|
|
|
|
|
plane_state->src_h = vdisplay << 16;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-12 21:20:10 +02:00
|
|
|
bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
2011-04-19 23:10:58 +01:00
|
|
|
struct drm_display_mode *mode,
|
2013-11-19 12:10:12 -05:00
|
|
|
struct intel_load_detect_pipe *old,
|
|
|
|
|
struct drm_modeset_acquire_ctx *ctx)
|
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-07 14:24:08 -08:00
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc;
|
2012-08-12 21:20:10 +02: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-07 14:24:08 -08:00
|
|
|
struct drm_crtc *possible_crtc;
|
2010-09-09 15:14:28 +01: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-07 14: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-05 22:51:56 +02:00
|
|
|
struct drm_framebuffer *fb;
|
2013-11-19 12:10:12 -05:00
|
|
|
struct drm_mode_config *config = &dev->mode_config;
|
2015-03-20 16:18:03 +02:00
|
|
|
struct drm_atomic_state *state = NULL;
|
2015-03-20 16:18:07 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
2015-04-21 17:13:01 +03:00
|
|
|
struct intel_crtc_state *crtc_state;
|
2013-11-19 12:10:12 -05:00
|
|
|
int ret, i = -1;
|
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-07 14:24:08 -08:00
|
|
|
|
2011-04-19 08:36:26 +01:00
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
2014-06-03 14:56:17 +03:00
|
|
|
connector->base.id, connector->name,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.id, encoder->name);
|
2011-04-19 08:36:26 +01:00
|
|
|
|
2013-11-19 12:10:12 -05:00
|
|
|
retry:
|
|
|
|
|
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
|
|
|
|
if (ret)
|
2015-07-13 16:30:26 +02:00
|
|
|
goto fail;
|
drm: Split connection_mutex out of mode_config.mutex (v3)
After the split-out of crtc locks from the big mode_config.mutex
there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID
properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other
modeset-relevant connector state (e.g. properties which control the
panel fitter).
The later is used by modeset operations. But they don't really care
about the former since it's allowed to e.g. enable a disconnected VGA
output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset
conversion Rob Clark needs to convert all modeset relevant locks into
w/w locks. This is required because the order of acquisition is
determined by how userspace supplies the atomic modeset data. This has
run into troubles in the detect path since the i915 load detect code
needs _both_ protections offered by the mode_config.mutex: It updates
probe state and it needs to change the modeset configuration to enable
the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a
plain mutex fits best, but for atomic modesets we really want a w/w
mutex. To fix this lets split out a new connection_mutex lock for the
modeset relevant parts.
For simplicity I've decided to only add one additional lock for all
connector/encoder links and modeset configuration states. We have
piles of different modeset objects in addition to those (like bridges
or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we
need to acquire this lock. Which means that fine-grained locking is
fairly irrelevant compared to the amount of time the full modeset will
take.
I've done a full audit, and there's just a few things that justify
special focus:
- Locking in drm_sysfs.c is almost completely absent. We should
sprinkle mode_config.connection_mutex over this file a bit, but
since it already lacks mode_config.mutex this patch wont make the
situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the
connector->encoder->crtc links and is called from many contexts.
Some look like they don't acquire mode_config.mutex, so this is
already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at
connector->dpms. Currently this happens without any locking, so is
already racy. I think radeon_hotplug_work_func should gain
mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already
racy.
- i915 load_detect code needs to acquire this lock. Which means the
w/w dance due to Rob's work will be nicely contained to _just_ this
function.
I've added fixme comments everywhere where it looks suspicious but in
the sysfs code. After a quick irc discussion with Dave Airlie it
sounds like the lack of locking in there is due to sysfs cleanup fun
at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to
get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
Cc: Alex Deucher <alexdeucher@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
2014-05-29 23:54:47 +02: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-07 14:24:08 -08:00
|
|
|
/*
|
|
|
|
|
* Algorithm gets a little messy:
|
2011-04-19 23:21:12 +01: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-07 14:24:08 -08:00
|
|
|
* - if the connector already has an assigned crtc, use it (but make
|
|
|
|
|
* sure it's on first)
|
2011-04-19 23:21:12 +01: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-07 14: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-19 23:18:09 +01:00
|
|
|
|
2013-11-19 12:10:12 -05:00
|
|
|
ret = drm_modeset_lock(&crtc->mutex, ctx);
|
2014-11-11 10:12:00 +01:00
|
|
|
if (ret)
|
2015-07-13 16:30:26 +02:00
|
|
|
goto fail;
|
2014-11-11 10:12:00 +01:00
|
|
|
ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
|
2013-11-19 12:10:12 -05:00
|
|
|
if (ret)
|
2015-07-13 16:30:26 +02:00
|
|
|
goto fail;
|
2012-12-12 00:35:33 +01:00
|
|
|
|
2012-08-12 19:27:11 +02:00
|
|
|
old->dpms_mode = connector->dpms;
|
2011-04-19 23:18:09 +01:00
|
|
|
old->load_detect_temp = false;
|
|
|
|
|
|
|
|
|
|
/* Make sure the crtc and connector are running */
|
2012-08-12 19:27:11 +02:00
|
|
|
if (connector->dpms != DRM_MODE_DPMS_ON)
|
|
|
|
|
connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
|
2011-04-19 23:18:09 +01:00
|
|
|
|
2011-04-19 23:10:58 +01: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find an unused one (if possible) */
|
2014-05-13 23:32:24 +01:00
|
|
|
for_each_crtc(dev, possible_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-07 14:24:08 -08:00
|
|
|
i++;
|
|
|
|
|
if (!(encoder->possible_crtcs & (1 << i)))
|
|
|
|
|
continue;
|
2015-02-25 13:12:16 -08:00
|
|
|
if (possible_crtc->state->enable)
|
2014-08-11 13:15:36 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
crtc = possible_crtc;
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we didn't find an unused CRTC, don't use any.
|
|
|
|
|
*/
|
|
|
|
|
if (!crtc) {
|
2011-04-19 23:10:58 +01:00
|
|
|
DRM_DEBUG_KMS("no pipe available for load-detect\n");
|
2015-07-13 16:30:26 +02:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-11-19 12:10:12 -05:00
|
|
|
ret = drm_modeset_lock(&crtc->mutex, ctx);
|
|
|
|
|
if (ret)
|
2015-07-13 16:30:26 +02:00
|
|
|
goto fail;
|
2014-11-11 10:12:00 +01:00
|
|
|
ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
|
|
|
|
|
if (ret)
|
2015-07-13 16:30:26 +02:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
2012-08-12 19:27:11 +02:00
|
|
|
old->dpms_mode = connector->dpms;
|
2011-04-19 23:18:09 +01:00
|
|
|
old->load_detect_temp = true;
|
2011-04-19 08:36:26 +01: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-07 14:24:08 -08:00
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
state = drm_atomic_state_alloc(dev);
|
|
|
|
|
if (!state)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
state->acquire_ctx = ctx;
|
|
|
|
|
|
2015-03-20 16:18:07 +02:00
|
|
|
connector_state = drm_atomic_get_connector_state(state, connector);
|
|
|
|
|
if (IS_ERR(connector_state)) {
|
|
|
|
|
ret = PTR_ERR(connector_state);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connector_state->crtc = crtc;
|
|
|
|
|
connector_state->best_encoder = &intel_encoder->base;
|
|
|
|
|
|
2015-04-21 17:13:01 +03:00
|
|
|
crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
|
|
|
|
|
if (IS_ERR(crtc_state)) {
|
|
|
|
|
ret = PTR_ERR(crtc_state);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 10:45:15 +02:00
|
|
|
crtc_state->base.active = crtc_state->base.enable = true;
|
2015-04-21 17:13:01 +03:00
|
|
|
|
2011-04-20 07:25:26 +01: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-07 14:24:08 -08:00
|
|
|
|
2011-04-19 08:36:26 +01: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-05 22:51:56 +02:00
|
|
|
fb = mode_fits_in_fbdev(dev, mode);
|
|
|
|
|
if (fb == NULL) {
|
2011-04-19 08:36:26 +01: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-05 22:51:56 +02:00
|
|
|
fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
|
|
|
|
|
old->release_fb = fb;
|
2011-04-19 08:36:26 +01: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-05 22:51:56 +02:00
|
|
|
if (IS_ERR(fb)) {
|
2011-04-19 08:36:26 +01:00
|
|
|
DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
|
2014-01-17 15:59:39 +02:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:09 +03:00
|
|
|
ret = intel_modeset_setup_plane_state(state, crtc, mode, fb, 0, 0);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2015-04-21 17:13:19 +03:00
|
|
|
drm_mode_copy(&crtc_state->base.mode, mode);
|
|
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
if (drm_atomic_commit(state)) {
|
2011-04-20 07:25:26 +01:00
|
|
|
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
|
2011-04-19 08:36:26 +01:00
|
|
|
if (old->release_fb)
|
|
|
|
|
old->release_fb->funcs->destroy(old->release_fb);
|
2014-01-17 15:59:39 +02:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
2015-03-03 17:31:21 +01:00
|
|
|
crtc->primary->crtc = crtc;
|
2011-04-19 23:10:58 +01: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-07 14:24:08 -08:00
|
|
|
/* let the connector get through one full cycle before testing */
|
2010-08-18 13:20:54 -07:00
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
2011-04-19 23:10:58 +01:00
|
|
|
return true;
|
2014-01-17 15:59:39 +02:00
|
|
|
|
2015-07-13 16:30:26 +02:00
|
|
|
fail:
|
2015-04-21 17:12:57 +03:00
|
|
|
drm_atomic_state_free(state);
|
|
|
|
|
state = NULL;
|
2015-03-20 16:18:03 +02:00
|
|
|
|
2013-11-19 12:10:12 -05:00
|
|
|
if (ret == -EDEADLK) {
|
|
|
|
|
drm_modeset_backoff(ctx);
|
|
|
|
|
goto retry;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-17 15:59:39 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2012-08-12 21:20:10 +02:00
|
|
|
void intel_release_load_detect_pipe(struct drm_connector *connector,
|
2015-03-20 16:18:02 +02:00
|
|
|
struct intel_load_detect_pipe *old,
|
|
|
|
|
struct drm_modeset_acquire_ctx *ctx)
|
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-07 14:24:08 -08:00
|
|
|
{
|
2015-03-20 16:18:03 +02:00
|
|
|
struct drm_device *dev = connector->dev;
|
2012-08-12 21:20:10 +02:00
|
|
|
struct intel_encoder *intel_encoder =
|
|
|
|
|
intel_attached_encoder(connector);
|
2010-09-09 15:14:28 +01:00
|
|
|
struct drm_encoder *encoder = &intel_encoder->base;
|
2012-12-12 00:35:33 +01:00
|
|
|
struct drm_crtc *crtc = encoder->crtc;
|
2014-01-17 15:59:39 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-03-20 16:18:03 +02:00
|
|
|
struct drm_atomic_state *state;
|
2015-03-20 16:18:07 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
2015-04-21 17:13:01 +03:00
|
|
|
struct intel_crtc_state *crtc_state;
|
2015-04-21 17:13:09 +03: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-07 14:24:08 -08:00
|
|
|
|
2011-04-19 08:36:26 +01:00
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
2014-06-03 14:56:17 +03:00
|
|
|
connector->base.id, connector->name,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.id, encoder->name);
|
2011-04-19 08:36:26 +01:00
|
|
|
|
2011-04-19 23:18:09 +01:00
|
|
|
if (old->load_detect_temp) {
|
2015-03-20 16:18:03 +02:00
|
|
|
state = drm_atomic_state_alloc(dev);
|
2015-03-20 16:18:07 +02:00
|
|
|
if (!state)
|
|
|
|
|
goto fail;
|
2015-03-20 16:18:03 +02:00
|
|
|
|
|
|
|
|
state->acquire_ctx = ctx;
|
|
|
|
|
|
2015-03-20 16:18:07 +02:00
|
|
|
connector_state = drm_atomic_get_connector_state(state, connector);
|
|
|
|
|
if (IS_ERR(connector_state))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2015-04-21 17:13:01 +03:00
|
|
|
crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
|
|
|
|
|
if (IS_ERR(crtc_state))
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2015-03-20 16:18:07 +02:00
|
|
|
connector_state->best_encoder = NULL;
|
|
|
|
|
connector_state->crtc = NULL;
|
|
|
|
|
|
2015-05-11 10:45:15 +02:00
|
|
|
crtc_state->base.enable = crtc_state->base.active = false;
|
2015-04-21 17:13:01 +03:00
|
|
|
|
2015-04-21 17:13:09 +03:00
|
|
|
ret = intel_modeset_setup_plane_state(state, crtc, NULL, NULL,
|
|
|
|
|
0, 0);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
ret = drm_atomic_commit(state);
|
2015-04-21 17:13:20 +03:00
|
|
|
if (ret)
|
|
|
|
|
goto fail;
|
2011-04-19 08:36:26 +01: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-10 20:42:17 +01:00
|
|
|
if (old->release_fb) {
|
|
|
|
|
drm_framebuffer_unregister_private(old->release_fb);
|
|
|
|
|
drm_framebuffer_unreference(old->release_fb);
|
|
|
|
|
}
|
2011-04-19 08:36:26 +01:00
|
|
|
|
2011-04-21 09:32:11 +01: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2010-03-25 11:48:48 -07:00
|
|
|
/* Switch crtc and encoder back off if necessary */
|
2012-08-12 19:27:11 +02:00
|
|
|
if (old->dpms_mode != DRM_MODE_DPMS_ON)
|
|
|
|
|
connector->funcs->dpms(connector, old->dpms_mode);
|
2015-03-20 16:18:07 +02:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
fail:
|
|
|
|
|
DRM_DEBUG_KMS("Couldn't release load detect pipe.\n");
|
|
|
|
|
drm_atomic_state_free(state);
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-09-09 14:06:37 +03:00
|
|
|
static int i9xx_pll_refclk(struct drm_device *dev,
|
2015-01-15 14:55:21 +02:00
|
|
|
const struct intel_crtc_state *pipe_config)
|
2013-09-09 14:06:37 +03:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
u32 dpll = pipe_config->dpll_hw_state.dpll;
|
|
|
|
|
|
|
|
|
|
if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
|
2013-12-09 18:54:16 +02:00
|
|
|
return dev_priv->vbt.lvds_ssc_freq;
|
2013-09-09 14:06:37 +03:00
|
|
|
else if (HAS_PCH_SPLIT(dev))
|
|
|
|
|
return 120000;
|
|
|
|
|
else if (!IS_GEN2(dev))
|
|
|
|
|
return 96000;
|
|
|
|
|
else
|
|
|
|
|
return 48000;
|
|
|
|
|
}
|
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
/* Returns the clock of the currently programmed mode of the given pipe. */
|
2013-06-27 00:39:25 +03:00
|
|
|
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *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-07 14:24:08 -08:00
|
|
|
{
|
2013-06-27 00:39:25 +03:00
|
|
|
struct drm_device *dev = crtc->base.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-07 14:24:08 -08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-27 00:39:25 +03:00
|
|
|
int pipe = pipe_config->cpu_transcoder;
|
2013-09-13 16:18:46 +03:00
|
|
|
u32 dpll = pipe_config->dpll_hw_state.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-07 14:24:08 -08:00
|
|
|
u32 fp;
|
|
|
|
|
intel_clock_t clock;
|
2015-06-22 23:35:51 +03:00
|
|
|
int port_clock;
|
2013-09-09 14:06:37 +03:00
|
|
|
int refclk = i9xx_pll_refclk(dev, 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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
|
2013-09-13 16:18:46 +03:00
|
|
|
fp = pipe_config->dpll_hw_state.fp0;
|
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-07 14:24:08 -08:00
|
|
|
else
|
2013-09-13 16:18:46 +03:00
|
|
|
fp = pipe_config->dpll_hw_state.fp1;
|
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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
2009-12-03 17:14:42 -05: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 00:32:17 +01:00
|
|
|
if (!IS_GEN2(dev)) {
|
2009-12-03 17:14:42 -05: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-07 14: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-07 14:24:08 -08:00
|
|
|
"mode\n", (int)(dpll & DPLL_MODE_MASK));
|
2013-06-27 00:39:25 +03: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-06-01 17:16:17 +02:00
|
|
|
if (IS_PINEVIEW(dev))
|
2015-06-22 23:35:51 +03:00
|
|
|
port_clock = pnv_calc_dpll_params(refclk, &clock);
|
2013-06-01 17:16:17 +02:00
|
|
|
else
|
2015-06-22 23:35:51 +03:00
|
|
|
port_clock = i9xx_calc_dpll_params(refclk, &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-07 14:24:08 -08:00
|
|
|
} else {
|
2014-01-10 14:06:46 +02:00
|
|
|
u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
|
2013-12-09 18:54:13 +02:00
|
|
|
bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
|
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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
if (is_lvds) {
|
|
|
|
|
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
|
|
|
|
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
2013-12-09 18:54:13 +02:00
|
|
|
|
|
|
|
|
if (lvds & LVDS_CLKB_POWER_UP)
|
|
|
|
|
clock.p2 = 7;
|
|
|
|
|
else
|
|
|
|
|
clock.p2 = 14;
|
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-07 14: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;
|
|
|
|
|
}
|
2013-09-09 14:06:37 +03:00
|
|
|
|
2015-06-22 23:35:51 +03:00
|
|
|
port_clock = i9xx_calc_dpll_params(refclk, &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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-09-13 16:00:08 +03:00
|
|
|
/*
|
|
|
|
|
* This value includes pixel_multiplier. We will use
|
2013-09-25 16:45:37 +01:00
|
|
|
* port_clock to compute adjusted_mode.crtc_clock in the
|
2013-09-13 16:00:08 +03:00
|
|
|
* encoder's get_config() function.
|
|
|
|
|
*/
|
2015-06-22 23:35:51 +03:00
|
|
|
pipe_config->port_clock = port_clock;
|
2013-06-27 00:39:25 +03:00
|
|
|
}
|
|
|
|
|
|
2013-09-13 15:59:11 +03:00
|
|
|
int intel_dotclock_calculate(int link_freq,
|
|
|
|
|
const struct intel_link_m_n *m_n)
|
2013-06-27 00:39:25 +03:00
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* The calculation for the data clock is:
|
2013-09-06 23:28:58 +03:00
|
|
|
* pixel_clock = ((m/n)*(link_clock * nr_lanes))/bpp
|
2013-06-27 00:39:25 +03:00
|
|
|
* But we want to avoid losing precison if possible, so:
|
2013-09-06 23:28:58 +03:00
|
|
|
* pixel_clock = ((m * link_clock * nr_lanes)/(n*bpp))
|
2013-06-27 00:39:25 +03:00
|
|
|
*
|
|
|
|
|
* and the link clock is simpler:
|
2013-09-06 23:28:58 +03:00
|
|
|
* link_clock = (m * link_clock) / n
|
2013-06-27 00:39:25 +03:00
|
|
|
*/
|
|
|
|
|
|
2013-09-13 15:59:11 +03:00
|
|
|
if (!m_n->link_n)
|
|
|
|
|
return 0;
|
2013-06-27 00:39:25 +03:00
|
|
|
|
2013-09-13 15:59:11 +03:00
|
|
|
return div_u64((u64)m_n->link_m * link_freq, m_n->link_n);
|
|
|
|
|
}
|
2013-06-27 00:39:25 +03:00
|
|
|
|
2013-09-13 16:00:08 +03:00
|
|
|
static void ironlake_pch_clock_get(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-09-13 15:59:11 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.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-07 14:24:08 -08:00
|
|
|
|
2013-09-13 16:00:08 +03:00
|
|
|
/* read out port_clock from the DPLL */
|
|
|
|
|
i9xx_crtc_clock_get(crtc, pipe_config);
|
2013-06-27 00:39:25 +03:00
|
|
|
|
|
|
|
|
/*
|
2013-09-13 16:00:08 +03:00
|
|
|
* This value does not include pixel_multiplier.
|
2013-09-25 16:45:37 +01:00
|
|
|
* We will check that port_clock and adjusted_mode.crtc_clock
|
2013-09-13 16:00:08 +03:00
|
|
|
* agree once we know their relationship in the encoder's
|
|
|
|
|
* get_config() function.
|
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-07 14:24:08 -08:00
|
|
|
*/
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_clock =
|
2013-09-13 16:00:08 +03:00
|
|
|
intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000,
|
|
|
|
|
&pipe_config->fdi_m_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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 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-17 10: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-07 14:24:08 -08:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-01-15 14:55:25 +02: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-07 14:24:08 -08:00
|
|
|
struct drm_display_mode *mode;
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state pipe_config;
|
2012-10-23 18:30:02 -02: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));
|
2013-09-13 16:18:46 +03:00
|
|
|
enum pipe 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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
|
|
|
|
if (!mode)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2013-06-27 00:39:25 +03:00
|
|
|
/*
|
|
|
|
|
* Construct a pipe_config sufficient for getting the clock info
|
|
|
|
|
* back out of crtc_clock_get.
|
|
|
|
|
*
|
|
|
|
|
* Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
|
|
|
|
|
* to use a real value here instead.
|
|
|
|
|
*/
|
2013-09-13 16:18:46 +03:00
|
|
|
pipe_config.cpu_transcoder = (enum transcoder) pipe;
|
2013-06-27 00:39:25 +03:00
|
|
|
pipe_config.pixel_multiplier = 1;
|
2013-09-13 16:18:46 +03:00
|
|
|
pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
|
|
|
|
|
pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
|
|
|
|
|
pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
|
2013-06-27 00:39:25 +03:00
|
|
|
i9xx_crtc_clock_get(intel_crtc, &pipe_config);
|
|
|
|
|
|
2013-09-23 17:48:20 +03:00
|
|
|
mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
|
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-07 14:24:08 -08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-21 12:31:41 +01:00
|
|
|
void intel_mark_busy(struct drm_device *dev)
|
|
|
|
|
{
|
2013-08-19 13:18:09 -03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2014-02-21 17:55:39 +00:00
|
|
|
if (dev_priv->mm.busy)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-03-07 20:08:08 -03:00
|
|
|
intel_runtime_pm_get(dev_priv);
|
2013-08-19 13:18:09 -03:00
|
|
|
i915_update_gfx_val(dev_priv);
|
2015-03-18 09:48:22 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 6)
|
|
|
|
|
gen6_rps_busy(dev_priv);
|
2014-02-21 17:55:39 +00:00
|
|
|
dev_priv->mm.busy = true;
|
2012-07-21 12:31:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_mark_idle(struct drm_device *dev)
|
2009-08-17 13:31:43 -07:00
|
|
|
{
|
2013-08-19 13:18:09 -03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2009-08-17 13:31:43 -07:00
|
|
|
|
2014-02-21 17:55:39 +00:00
|
|
|
if (!dev_priv->mm.busy)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
dev_priv->mm.busy = false;
|
|
|
|
|
|
2014-02-07 19:12:47 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 6)
|
drm/i915: Boost RPS frequency for CPU stalls
If we encounter a situation where the CPU blocks waiting for results
from the GPU, give the GPU a kick to boost its the frequency.
This should work to reduce user interface stalls and to quickly promote
mesa to high frequencies - but the cost is that our requested frequency
stalls high (as we do not idle for long enough before rc6 to start
reducing frequencies, nor are we aggressive at down clocking an
underused GPU). However, this should be mitigated by rc6 itself powering
off the GPU when idle, and that energy use is dependent upon the workload
of the GPU in addition to its frequency (e.g. the math or sampler
functions only consume power when used). Still, this is likely to
adversely affect light workloads.
In particular, this nearly eliminates the highly noticeable wake-up lag
in animations from idle. For example, expose or workspace transitions.
(However, given the situation where we fail to downclock, our requested
frequency is almost always the maximum, except for Baytrail where we
manually downclock upon idling. This often masks the latency of
upclocking after being idle, so animations are typically smooth - at the
cost of increased power consumption.)
Stéphane raised the concern that this will punish good applications and
reward bad applications - but due to the nature of how mesa performs its
client throttling, I believe all mesa applications will be roughly
equally affected. To address this concern, and to prevent applications
like compositors from permanently boosting the RPS state, we ratelimit the
frequency of the wait-boosts each client recieves.
Unfortunately, this techinique is ineffective with Ironlake - which also
has dynamic render power states and suffers just as dramatically. For
Ironlake, the thermal/power headroom is shared with the CPU through
Intelligent Power Sharing and the intel-ips module. This leaves us with
no GPU boost frequencies available when coming out of idle, and due to
hardware limitations we cannot change the arbitration between the CPU and
GPU quickly enough to be effective.
v2: Limit each client to receiving a single boost for each active period.
Tested by QA to only marginally increase power, and to demonstrably
increase throughput in games. No latency measurements yet.
v3: Cater for front-buffer rendering with manual throttling.
v4: Tidy up.
v5: Sadly the compositor needs frequent boosts as it may never idle, but
due to its picking mechanism (using ReadPixels) may require frequent
waits. Those waits, along with the waits for the vrefresh swap, conspire
to keep the GPU at low frequencies despite the interactive latency. To
overcome this we ditch the one-boost-per-active-period and just ratelimit
the number of wait-boosts each client can receive.
Reported-and-tested-by: Paul Neumann <paul104x@yahoo.de>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68716
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Kenneth Graunke <kenneth@whitecape.org>
Cc: Stéphane Marchesin <stephane.marchesin@gmail.com>
Cc: Owen Taylor <otaylor@redhat.com>
Cc: "Meng, Mengmeng" <mengmeng.meng@intel.com>
Cc: "Zhuang, Lena" <lena.zhuang@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
[danvet: No extern for function prototypes in headers.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-09-25 17:34:56 +01:00
|
|
|
gen6_rps_idle(dev->dev_private);
|
2014-02-21 13:52:19 -03:00
|
|
|
|
2014-03-07 20:08:08 -03:00
|
|
|
intel_runtime_pm_put(dev_priv);
|
2009-08-17 13:31:43 -07: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-07 14:24:08 -08:00
|
|
|
static void intel_crtc_destroy(struct drm_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2010-08-20 22:26:30 +02:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct intel_unpin_work *work;
|
|
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2010-08-20 22:26:30 +02:00
|
|
|
work = intel_crtc->unpin_work;
|
|
|
|
|
intel_crtc->unpin_work = NULL;
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2010-08-20 22:26:30 +02:00
|
|
|
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
drm_crtc_cleanup(crtc);
|
2010-08-20 22:26:30 +02: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-07 14:24:08 -08:00
|
|
|
kfree(intel_crtc);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
static void intel_unpin_work_fn(struct work_struct *__work)
|
|
|
|
|
{
|
|
|
|
|
struct intel_unpin_work *work =
|
|
|
|
|
container_of(__work, struct intel_unpin_work, work);
|
2015-06-24 21:59:34 +03:00
|
|
|
struct intel_crtc *crtc = to_intel_crtc(work->crtc);
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_plane *primary = crtc->base.primary;
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2012-11-01 09:26:26 +00:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2015-06-24 21:59:34 +03:00
|
|
|
intel_unpin_fb_obj(work->old_fb, primary->state);
|
2010-11-08 19:18:58 +00:00
|
|
|
drm_gem_object_unreference(&work->pending_flip_obj->base);
|
2010-11-10 16:40:20 +00:00
|
|
|
|
2014-11-24 18:49:37 +00:00
|
|
|
if (work->flip_queued_req)
|
2014-12-05 13:49:33 +00:00
|
|
|
i915_gem_request_assign(&work->flip_queued_req, NULL);
|
2012-11-01 09:26:26 +00:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
2015-06-24 21:59:34 +03:00
|
|
|
intel_frontbuffer_flip_complete(dev, to_intel_plane(primary)->frontbuffer_bit);
|
2015-02-16 14:31:49 +00:00
|
|
|
drm_framebuffer_unreference(work->old_fb);
|
drm/i915: Track frontbuffer invalidation/flushing
So these are the guts of the new beast. This tracks when a frontbuffer
gets invalidated (due to frontbuffer rendering) and hence should be
constantly scaned out, and when it's flushed again and can be
compressed/one-shot-upload.
Rules for flushing are simple: The frontbuffer needs one more full
upload starting from the next vblank. Which means that the flushing
can _only_ be called once the frontbuffer update has been latched.
But this poses a problem for pageflips: We can't just delay the
flushing until the pageflip is latched, since that would pose the risk
that we override frontbuffer rendering that has been scheduled
in-between the pageflip ioctl and the actual latching.
To handle this track asynchronous invalidations (and also pageflip)
state per-ring and delay any in-between flushing until the rendering
has completed. And also cancel any delayed flushing if we get a new
invalidation request (whether delayed or not).
Also call intel_mark_fb_busy in both cases in all cases to make sure
that we keep the screen at the highest refresh rate both on flips,
synchronous plane updates and for frontbuffer rendering.
v2: Lots of improvements
Suggestions from Chris:
- Move invalidate/flush in flush_*_domain and set_to_*_domain.
- Drop the flush in busy_ioctl since it's redundant. Was a leftover
from an earlier concept to track flips/delayed flushes.
- Don't forget about the initial modeset enable/final disable.
Suggested by Chris.
Track flips accurately, too. Since flips complete independently of
rendering we need to track pending flips in a separate mask. Again if
an invalidate happens we need to cancel the evenutal flush to avoid
races.
v3:
Provide correct header declarations for flip functions. Currently not
needed outside of intel_display.c, but part of the proper interface.
v4: Add proper domain management to fbcon so that the fbcon buffer is
also tracked correctly.
v5: Fixup locking around the fbcon set_to_gtt_domain call.
v6: More comments from Chris:
- Split out fbcon changes.
- Drop superflous checks for potential scanout before calling intel_fb
functions - we can micro-optimize this later.
- s/intel_fb_/intel_fb_obj_/ to make it clear that this deals in gem
object. We already have precedence for fb_obj in the pin_and_fence
functions.
v7: Clarify the semantics of the flip flush handling by renaming
things a bit:
- Don't go through a gem object but take the relevant frontbuffer bits
directly. These functions center on the plane, the actual object is
irrelevant - even a flip to the same object as already active should
cause a flush.
- Add a new intel_frontbuffer_flip for synchronous plane updates. It
currently just calls intel_frontbuffer_flush since the implemenation
differs.
This way we achieve a clear split between one-shot update events on
one side and frontbuffer rendering with potentially a very long delay
between the invalidate and flush.
Chris and I also had some discussions about mark_busy and whether it
is appropriate to call from flush. But mark busy is a state which
should be derived from the 3 events (invalidate, flush, flip) we now
have by the users, like psr does by tracking relevant information in
psr.busy_frontbuffer_bits. DRRS (the only real use of mark_busy for
frontbuffer) needs to have similar logic. With that the overall
mark_busy in the core could be removed.
v8: Only when retiring gpu buffers only flush frontbuffer bits we
actually invalidated in a batch. Just for safety since before any
additional usage/invalidate we should always retire current rendering.
Suggested by Chris Wilson.
v9: Actually use intel_frontbuffer_flip in all appropriate places.
Spotted by Chris.
v10: Address more comments from Chris:
- Don't call _flip in set_base when the crtc is inactive, avoids redunancy
in the modeset case with the initial enabling of all planes.
- Add comments explaining that the initial/final plane enable/disable
still has work left to do before it's fully generic.
v11: Only invalidate for gtt/cpu access when writing. Spotted by Chris.
v12: s/_flush/_flip/ in intel_overlay.c per Chris' comment.
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-19 16:01:59 +02:00
|
|
|
|
2015-06-24 21:59:34 +03:00
|
|
|
BUG_ON(atomic_read(&crtc->unpin_work_count) == 0);
|
|
|
|
|
atomic_dec(&crtc->unpin_work_count);
|
2012-11-01 09:26:26 +00:00
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
kfree(work);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-26 10:35:20 -07:00
|
|
|
static void do_intel_finish_page_flip(struct drm_device *dev,
|
2010-12-09 07:00:07 +01:00
|
|
|
struct drm_crtc *crtc)
|
2009-11-18 11:25:18 -05:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2014-09-15 14:55:23 +02:00
|
|
|
/*
|
|
|
|
|
* This is called both by irq handlers and the reset code (to complete
|
|
|
|
|
* lost pageflips) so needs the full irqsave spinlocks.
|
|
|
|
|
*/
|
2009-11-18 11:25:18 -05:00
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
|
|
work = intel_crtc->unpin_work;
|
2012-12-03 11:36:30 +00:00
|
|
|
|
|
|
|
|
/* Ensure we don't miss a work->pending update ... */
|
|
|
|
|
smp_rmb();
|
|
|
|
|
|
|
|
|
|
if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
|
2009-11-18 11:25:18 -05:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
page_flip_completed(intel_crtc);
|
2010-12-08 04:07:19 +01:00
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-26 10:35:20 -07:00
|
|
|
void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-03-26 10:35:20 -07:00
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
|
|
2010-12-09 07:00:07 +01:00
|
|
|
do_intel_finish_page_flip(dev, crtc);
|
2010-03-26 10:35:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
|
|
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-03-26 10:35:20 -07:00
|
|
|
struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
|
|
|
|
|
|
2010-12-09 07:00:07 +01:00
|
|
|
do_intel_finish_page_flip(dev, crtc);
|
2010-03-26 10:35:20 -07:00
|
|
|
}
|
|
|
|
|
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
/* Is 'a' after or equal to 'b'? */
|
|
|
|
|
static bool g4x_flip_count_after_eq(u32 a, u32 b)
|
|
|
|
|
{
|
|
|
|
|
return !((a - b) & 0x80000000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool page_flip_finished(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2014-05-27 21:33:09 +03:00
|
|
|
if (i915_reset_in_progress(&dev_priv->gpu_error) ||
|
|
|
|
|
crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
|
|
|
|
|
return true;
|
|
|
|
|
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
/*
|
|
|
|
|
* The relevant registers doen't exist on pre-ctg.
|
|
|
|
|
* As the flip done interrupt doesn't trigger for mmio
|
|
|
|
|
* flips on gmch platforms, a flip count check isn't
|
|
|
|
|
* really needed there. But since ctg has the registers,
|
|
|
|
|
* include it in the check anyway.
|
|
|
|
|
*/
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A DSPSURFLIVE check isn't enough in case the mmio and CS flips
|
|
|
|
|
* used the same base address. In that case the mmio flip might
|
|
|
|
|
* have completed, but the CS hasn't even executed the flip yet.
|
|
|
|
|
*
|
|
|
|
|
* A flip count check isn't enough as the CS might have updated
|
|
|
|
|
* the base address just after start of vblank, but before we
|
|
|
|
|
* managed to process the interrupt. This means we'd complete the
|
|
|
|
|
* CS flip too soon.
|
|
|
|
|
*
|
|
|
|
|
* Combining both checks should get us a good enough result. It may
|
|
|
|
|
* still happen that the CS flip has been executed, but has not
|
|
|
|
|
* yet actually completed. But in case the base address is the same
|
|
|
|
|
* anyway, we don't really care.
|
|
|
|
|
*/
|
|
|
|
|
return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
|
|
|
|
|
crtc->unpin_work->gtt_offset &&
|
2015-09-18 20:03:42 +03:00
|
|
|
g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)),
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
crtc->unpin_work->flip_count);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
void intel_prepare_page_flip(struct drm_device *dev, int plane)
|
|
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2009-11-18 11:25:18 -05:00
|
|
|
struct intel_crtc *intel_crtc =
|
|
|
|
|
to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
2014-09-15 14:55:23 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is called both by irq handlers and the reset code (to complete
|
|
|
|
|
* lost pageflips) so needs the full irqsave spinlocks.
|
|
|
|
|
*
|
|
|
|
|
* NB: An MMIO update of the plane base pointer will also
|
2012-12-03 11:36:30 +00:00
|
|
|
* generate a page-flip completion irq, i.e. every modeset
|
|
|
|
|
* is also accompanied by a spurious intel_prepare_page_flip().
|
|
|
|
|
*/
|
2009-11-18 11:25:18 -05:00
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
if (intel_crtc->unpin_work && page_flip_finished(intel_crtc))
|
2012-12-03 11:36:30 +00:00
|
|
|
atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
|
2009-11-18 11:25:18 -05:00
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
static inline void intel_mark_page_flip_active(struct intel_unpin_work *work)
|
2012-12-03 11:36:30 +00:00
|
|
|
{
|
|
|
|
|
/* Ensure that the work item is consistent when activating it ... */
|
|
|
|
|
smp_wmb();
|
2015-10-10 10:44:32 +01:00
|
|
|
atomic_set(&work->pending, INTEL_FLIP_PENDING);
|
2012-12-03 11:36:30 +00:00
|
|
|
/* and that it is marked active as soon as the irq could fire. */
|
|
|
|
|
smp_wmb();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-16 09:19:13 -07:00
|
|
|
static int intel_gen2_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 09:19:13 -07:00
|
|
|
{
|
2015-05-29 17:43:48 +01:00
|
|
|
struct intel_engine_cs *ring = req->ring;
|
2011-06-16 09:19:13 -07:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
u32 flip_mask;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2015-05-29 17:44:07 +01:00
|
|
|
ret = intel_ring_begin(req, 6);
|
2011-06-16 09:19:13 -07:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2011-06-16 09:19:13 -07: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-26 23:28:05 +02: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]);
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
|
2012-04-26 23:28:05 +02:00
|
|
|
intel_ring_emit(ring, 0); /* aux display base address, unused */
|
2012-12-03 11:36:30 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(intel_crtc->unpin_work);
|
2012-04-17 19:35:53 +01:00
|
|
|
return 0;
|
2011-06-16 09:19:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_gen3_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 09:19:13 -07:00
|
|
|
{
|
2015-05-29 17:43:48 +01:00
|
|
|
struct intel_engine_cs *ring = req->ring;
|
2011-06-16 09:19:13 -07:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
u32 flip_mask;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2015-05-29 17:44:07 +01:00
|
|
|
ret = intel_ring_begin(req, 6);
|
2011-06-16 09:19:13 -07:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2011-06-16 09:19:13 -07:00
|
|
|
|
|
|
|
|
if (intel_crtc->plane)
|
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
|
|
else
|
|
|
|
|
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
2012-04-26 23:28:05 +02: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]);
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
|
2012-04-26 23:28:05 +02:00
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(intel_crtc->unpin_work);
|
2012-04-17 19:35:53 +01:00
|
|
|
return 0;
|
2011-06-16 09:19:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_gen4_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 09:19:13 -07:00
|
|
|
{
|
2015-05-29 17:43:48 +01:00
|
|
|
struct intel_engine_cs *ring = req->ring;
|
2011-06-16 09:19:13 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
uint32_t pf, pipesrc;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2015-05-29 17:44:07 +01:00
|
|
|
ret = intel_ring_begin(req, 4);
|
2011-06-16 09:19:13 -07:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2011-06-16 09:19:13 -07: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-26 23:28:05 +02:00
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
|
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
|
intel_ring_emit(ring, fb->pitches[0]);
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
|
2012-07-05 12:17:30 +02:00
|
|
|
obj->tiling_mode);
|
2011-06-16 09:19:13 -07: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-26 23:28:05 +02:00
|
|
|
intel_ring_emit(ring, pf | pipesrc);
|
2012-12-03 11:36:30 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(intel_crtc->unpin_work);
|
2012-04-17 19:35:53 +01:00
|
|
|
return 0;
|
2011-06-16 09:19:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_gen6_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 09:19:13 -07:00
|
|
|
{
|
2015-05-29 17:43:48 +01:00
|
|
|
struct intel_engine_cs *ring = req->ring;
|
2011-06-16 09:19:13 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
uint32_t pf, pipesrc;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2015-05-29 17:44:07 +01:00
|
|
|
ret = intel_ring_begin(req, 4);
|
2011-06-16 09:19:13 -07:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2011-06-16 09:19:13 -07:00
|
|
|
|
2012-04-26 23:28:05 +02: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);
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
|
2011-06-16 09:19:13 -07:00
|
|
|
|
2012-05-07 11:30:46 +02: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-16 09:19:13 -07:00
|
|
|
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
|
2012-04-26 23:28:05 +02:00
|
|
|
intel_ring_emit(ring, pf | pipesrc);
|
2012-12-03 11:36:30 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(intel_crtc->unpin_work);
|
2012-04-17 19:35:53 +01:00
|
|
|
return 0;
|
2011-06-16 09:19:13 -07:00
|
|
|
}
|
|
|
|
|
|
2011-06-16 12:18:54 -07:00
|
|
|
static int intel_gen7_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 12:18:54 -07:00
|
|
|
{
|
2015-05-29 17:43:48 +01:00
|
|
|
struct intel_engine_cs *ring = req->ring;
|
2011-06-16 12:18:54 -07:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2012-05-23 14:02:00 +02:00
|
|
|
uint32_t plane_bit = 0;
|
2013-08-26 20:58:12 +01:00
|
|
|
int len, ret;
|
|
|
|
|
|
2014-05-18 02:24:50 +02:00
|
|
|
switch (intel_crtc->plane) {
|
2012-05-23 14:02:00 +02:00
|
|
|
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");
|
2014-04-15 21:41:38 +03:00
|
|
|
return -ENODEV;
|
2012-05-23 14:02:00 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-26 20:58:12 +01:00
|
|
|
len = 4;
|
2014-04-07 20:24:34 +01:00
|
|
|
if (ring->id == RCS) {
|
2013-08-26 20:58:12 +01:00
|
|
|
len += 6;
|
2014-04-07 20:24:34 +01:00
|
|
|
/*
|
|
|
|
|
* On Gen 8, SRM is now taking an extra dword to accommodate
|
|
|
|
|
* 48bits addresses, and we need a NOOP for the batch size to
|
|
|
|
|
* stay even.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_GEN8(dev))
|
|
|
|
|
len += 2;
|
|
|
|
|
}
|
2013-08-26 20:58:12 +01:00
|
|
|
|
2014-02-11 19:52:06 +02:00
|
|
|
/*
|
|
|
|
|
* BSpec MI_DISPLAY_FLIP for IVB:
|
|
|
|
|
* "The full packet must be contained within the same cache line."
|
|
|
|
|
*
|
|
|
|
|
* Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
|
|
|
|
|
* cacheline, if we ever start emitting more commands before
|
|
|
|
|
* the MI_DISPLAY_FLIP we may need to first emit everything else,
|
|
|
|
|
* then do the cacheline alignment, and finally emit the
|
|
|
|
|
* MI_DISPLAY_FLIP.
|
|
|
|
|
*/
|
2015-05-29 17:44:06 +01:00
|
|
|
ret = intel_ring_cacheline_align(req);
|
2014-02-11 19:52:06 +02:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2014-02-11 19:52:06 +02:00
|
|
|
|
2015-05-29 17:44:07 +01:00
|
|
|
ret = intel_ring_begin(req, len);
|
2011-06-16 12:18:54 -07:00
|
|
|
if (ret)
|
2014-04-15 21:41:38 +03:00
|
|
|
return ret;
|
2011-06-16 12:18:54 -07:00
|
|
|
|
2013-08-26 20:58:12 +01:00
|
|
|
/* Unmask the flip-done completion message. Note that the bspec says that
|
|
|
|
|
* we should do this for both the BCS and RCS, and that we must not unmask
|
|
|
|
|
* more than one flip event at any time (or ensure that one flip message
|
|
|
|
|
* can be sent by waiting for flip-done prior to queueing new flips).
|
|
|
|
|
* Experimentation says that BCS works despite DERRMR masking all
|
|
|
|
|
* flip-done completion events and that unmasking all planes at once
|
|
|
|
|
* for the RCS also doesn't appear to drop events. Setting the DERRMR
|
|
|
|
|
* to zero does lead to lockups within MI_DISPLAY_FLIP.
|
|
|
|
|
*/
|
|
|
|
|
if (ring->id == RCS) {
|
|
|
|
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
2015-11-04 23:20:07 +02:00
|
|
|
intel_ring_emit_reg(ring, DERRMR);
|
2013-08-26 20:58:12 +01:00
|
|
|
intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
|
|
|
|
|
DERRMR_PIPEB_PRI_FLIP_DONE |
|
|
|
|
|
DERRMR_PIPEC_PRI_FLIP_DONE));
|
2014-04-07 20:24:34 +01:00
|
|
|
if (IS_GEN8(dev))
|
2015-08-04 16:22:20 +01:00
|
|
|
intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
|
2014-04-07 20:24:34 +01:00
|
|
|
MI_SRM_LRM_GLOBAL_GTT);
|
|
|
|
|
else
|
2015-08-04 16:22:20 +01:00
|
|
|
intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
|
2014-04-07 20:24:34 +01:00
|
|
|
MI_SRM_LRM_GLOBAL_GTT);
|
2015-11-04 23:20:07 +02:00
|
|
|
intel_ring_emit_reg(ring, DERRMR);
|
2013-08-26 20:58:12 +01:00
|
|
|
intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
|
2014-04-07 20:24:34 +01:00
|
|
|
if (IS_GEN8(dev)) {
|
|
|
|
|
intel_ring_emit(ring, 0);
|
|
|
|
|
intel_ring_emit(ring, MI_NOOP);
|
|
|
|
|
}
|
2013-08-26 20:58:12 +01:00
|
|
|
}
|
|
|
|
|
|
2012-05-23 14:02:00 +02:00
|
|
|
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
|
2011-12-20 00:06:49 +02:00
|
|
|
intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
|
2011-06-16 12:18:54 -07:00
|
|
|
intel_ring_emit(ring, (MI_NOOP));
|
2012-12-03 11:36:30 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(intel_crtc->unpin_work);
|
2012-04-17 19:35:53 +01:00
|
|
|
return 0;
|
2011-06-16 12:18:54 -07:00
|
|
|
}
|
|
|
|
|
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
static bool use_mmio_flip(struct intel_engine_cs *ring,
|
|
|
|
|
struct drm_i915_gem_object *obj)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This is not being used for older platforms, because
|
|
|
|
|
* non-availability of flip done interrupt forces us to use
|
|
|
|
|
* CS flips. Older platforms derive flip done using some clever
|
|
|
|
|
* tricks involving the flip_pending status bits and vblank irqs.
|
|
|
|
|
* So using MMIO flips there would disrupt this mechanism.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-07-08 10:40:30 +01:00
|
|
|
if (ring == NULL)
|
|
|
|
|
return true;
|
|
|
|
|
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
if (INTEL_INFO(ring->dev)->gen < 5)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (i915.use_mmio_flip < 0)
|
|
|
|
|
return false;
|
|
|
|
|
else if (i915.use_mmio_flip > 0)
|
|
|
|
|
return true;
|
2014-07-24 17:04:34 +01:00
|
|
|
else if (i915.enable_execlists)
|
|
|
|
|
return true;
|
2015-11-25 18:43:38 -08:00
|
|
|
else if (obj->base.dma_buf &&
|
|
|
|
|
!reservation_object_test_signaled_rcu(obj->base.dma_buf->resv,
|
|
|
|
|
false))
|
|
|
|
|
return true;
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
else
|
2015-04-27 13:41:17 +01:00
|
|
|
return ring != i915_gem_request_get_ring(obj->last_write_req);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
}
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
|
2015-10-20 16:20:21 +01:00
|
|
|
unsigned int rotation,
|
2015-10-10 10:44:32 +01:00
|
|
|
struct intel_unpin_work *work)
|
2014-11-20 14:58:16 +00:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
|
|
|
|
|
const enum pipe pipe = intel_crtc->pipe;
|
2015-10-20 16:20:21 +01:00
|
|
|
u32 ctl, stride, tile_height;
|
2014-11-20 14:58:16 +00:00
|
|
|
|
|
|
|
|
ctl = I915_READ(PLANE_CTL(pipe, 0));
|
|
|
|
|
ctl &= ~PLANE_CTL_TILED_MASK;
|
2015-04-20 16:22:48 +01:00
|
|
|
switch (fb->modifier[0]) {
|
|
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
2014-11-20 14:58:16 +00:00
|
|
|
ctl |= PLANE_CTL_TILED_X;
|
2015-04-20 16:22:48 +01:00
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
ctl |= PLANE_CTL_TILED_Y;
|
|
|
|
|
break;
|
|
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
|
|
|
ctl |= PLANE_CTL_TILED_YF;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
MISSING_CASE(fb->modifier[0]);
|
|
|
|
|
}
|
2014-11-20 14:58:16 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The stride is either expressed as a multiple of 64 bytes chunks for
|
|
|
|
|
* linear buffers or in number of tiles for tiled buffers.
|
|
|
|
|
*/
|
2015-10-20 16:20:21 +01:00
|
|
|
if (intel_rotation_90_or_270(rotation)) {
|
|
|
|
|
/* stride = Surface height in tiles */
|
|
|
|
|
tile_height = intel_tile_height(dev, fb->pixel_format,
|
|
|
|
|
fb->modifier[0], 0);
|
|
|
|
|
stride = DIV_ROUND_UP(fb->height, tile_height);
|
|
|
|
|
} else {
|
|
|
|
|
stride = fb->pitches[0] /
|
|
|
|
|
intel_fb_stride_alignment(dev, fb->modifier[0],
|
|
|
|
|
fb->pixel_format);
|
|
|
|
|
}
|
2014-11-20 14:58:16 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
|
|
|
|
|
* PLANE_SURF updates, the update is then guaranteed to be atomic.
|
|
|
|
|
*/
|
|
|
|
|
I915_WRITE(PLANE_CTL(pipe, 0), ctl);
|
|
|
|
|
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
I915_WRITE(PLANE_SURF(pipe, 0), work->gtt_offset);
|
2014-11-20 14:58:16 +00:00
|
|
|
POSTING_READ(PLANE_SURF(pipe, 0));
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
|
|
|
|
|
struct intel_unpin_work *work)
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
{
|
|
|
|
|
struct drm_device *dev = intel_crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_framebuffer *intel_fb =
|
|
|
|
|
to_intel_framebuffer(intel_crtc->base.primary->fb);
|
|
|
|
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t reg = DSPCNTR(intel_crtc->plane);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
u32 dspcntr;
|
|
|
|
|
|
|
|
|
|
dspcntr = I915_READ(reg);
|
|
|
|
|
|
2014-10-25 00:11:11 +01:00
|
|
|
if (obj->tiling_mode != I915_TILING_NONE)
|
|
|
|
|
dspcntr |= DISPPLANE_TILED;
|
|
|
|
|
else
|
|
|
|
|
dspcntr &= ~DISPPLANE_TILED;
|
|
|
|
|
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
I915_WRITE(reg, dspcntr);
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
I915_WRITE(DSPSURF(intel_crtc->plane), work->gtt_offset);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
POSTING_READ(DSPSURF(intel_crtc->plane));
|
2014-11-20 14:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* XXX: This is the temporary way to update the plane registers until we get
|
|
|
|
|
* around to using the usual plane update functions for MMIO flips
|
|
|
|
|
*/
|
2015-10-10 10:44:32 +01:00
|
|
|
static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
|
2014-11-20 14:58:16 +00:00
|
|
|
{
|
2015-10-10 10:44:32 +01:00
|
|
|
struct intel_crtc *crtc = mmio_flip->crtc;
|
|
|
|
|
struct intel_unpin_work *work;
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&crtc->base.dev->event_lock);
|
|
|
|
|
work = crtc->unpin_work;
|
|
|
|
|
spin_unlock_irq(&crtc->base.dev->event_lock);
|
|
|
|
|
if (work == NULL)
|
|
|
|
|
return;
|
2014-11-20 14:58:16 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_mark_page_flip_active(work);
|
2014-11-20 14:58:16 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_pipe_update_start(crtc);
|
2014-11-20 14:58:16 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
|
2015-10-20 16:20:21 +01:00
|
|
|
skl_do_mmio_flip(crtc, mmio_flip->rotation, work);
|
2014-11-20 14:58:16 +00:00
|
|
|
else
|
|
|
|
|
/* use_mmio_flip() retricts MMIO flips to ilk+ */
|
2015-10-10 10:44:32 +01:00
|
|
|
ilk_do_mmio_flip(crtc, work);
|
2014-11-20 14:58:16 +00:00
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_pipe_update_end(crtc);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
}
|
|
|
|
|
|
2014-10-28 15:10:14 +02:00
|
|
|
static void intel_mmio_flip_work_func(struct work_struct *work)
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
{
|
2015-04-27 13:41:16 +01:00
|
|
|
struct intel_mmio_flip *mmio_flip =
|
|
|
|
|
container_of(work, struct intel_mmio_flip, work);
|
2015-11-25 18:43:38 -08:00
|
|
|
struct intel_framebuffer *intel_fb =
|
|
|
|
|
to_intel_framebuffer(mmio_flip->crtc->base.primary->fb);
|
|
|
|
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
if (mmio_flip->req) {
|
2015-05-21 14:21:25 +02:00
|
|
|
WARN_ON(__i915_wait_request(mmio_flip->req,
|
2015-04-27 13:41:16 +01:00
|
|
|
mmio_flip->crtc->reset_counter,
|
2015-04-27 13:41:21 +01:00
|
|
|
false, NULL,
|
|
|
|
|
&mmio_flip->i915->rps.mmioflips));
|
2015-10-10 10:44:32 +01:00
|
|
|
i915_gem_request_unreference__unlocked(mmio_flip->req);
|
|
|
|
|
}
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
|
2015-11-25 18:43:38 -08:00
|
|
|
/* For framebuffer backed by dmabuf, wait for fence */
|
|
|
|
|
if (obj->base.dma_buf)
|
|
|
|
|
WARN_ON(reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
|
|
|
|
|
false, false,
|
|
|
|
|
MAX_SCHEDULE_TIMEOUT) < 0);
|
|
|
|
|
|
2015-10-10 10:44:32 +01:00
|
|
|
intel_do_mmio_flip(mmio_flip);
|
2015-04-27 13:41:16 +01:00
|
|
|
kfree(mmio_flip);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_queue_mmio_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
2015-10-20 16:20:21 +01:00
|
|
|
struct drm_i915_gem_object *obj)
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
{
|
2015-04-27 13:41:16 +01:00
|
|
|
struct intel_mmio_flip *mmio_flip;
|
|
|
|
|
|
|
|
|
|
mmio_flip = kmalloc(sizeof(*mmio_flip), GFP_KERNEL);
|
|
|
|
|
if (mmio_flip == NULL)
|
|
|
|
|
return -ENOMEM;
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
|
2015-04-27 13:41:21 +01:00
|
|
|
mmio_flip->i915 = to_i915(dev);
|
2015-05-21 14:21:25 +02:00
|
|
|
mmio_flip->req = i915_gem_request_reference(obj->last_write_req);
|
2015-04-27 13:41:16 +01:00
|
|
|
mmio_flip->crtc = to_intel_crtc(crtc);
|
2015-10-20 16:20:21 +01:00
|
|
|
mmio_flip->rotation = crtc->primary->state->rotation;
|
2014-11-06 11:03:40 +02:00
|
|
|
|
2015-04-27 13:41:16 +01:00
|
|
|
INIT_WORK(&mmio_flip->work, intel_mmio_flip_work_func);
|
|
|
|
|
schedule_work(&mmio_flip->work);
|
drm/i915: Replaced Blitter ring based flips with MMIO flips
This patch enables the framework for using MMIO based flip calls,
in contrast with the CS based flip calls which are being used currently.
MMIO based flip calls can be enabled on architectures where
Render and Blitter engines reside in different power wells. The
decision to use MMIO flips can be made based on workloads to give
100% residency for Media power well.
v2: The MMIO flips now use the interrupt driven mechanism for issuing the
flips when target seqno is reached. (Incorporating Ville's idea)
v3: Rebasing on latest code. Code restructuring after incorporating
Damien's comments
v4: Addressing Ville's review comments
-general cleanup
-updating only base addr instead of calling update_primary_plane
-extending patch for gen5+ platforms
v5: Addressed Ville's review comments
-Making mmio flip vs cs flip selection based on module parameter
-Adding check for DRIVER_MODESET feature in notify_ring before calling
notify mmio flip.
-Other changes mostly in function arguments
v6: -Having a seperate function to check condition for using mmio flips (Ville)
-propogating error code from i915_gem_check_olr (Ville)
v7: -Adding __must_check with i915_gem_check_olr (Chris)
-Renaming mmio_flip_data to mmio_flip (Chris)
-Rebasing on latest nightly
v8: -Rebasing on latest code
-squash 3rd patch in series(mmio setbase vs page flip race) with this patch
-Added new tiling mode update in intel_do_mmio_flip (Chris)
v9: -check for obj->last_write_seqno being 0 instead of obj->ring being NULL in
intel_postpone_flip, as this is a more restrictive condition (Chris)
v10: -Applied Chris's suggestions for squashing patches 2,3 into this patch.
These patches make the selection of CS vs MMIO flip at the page flip time, and
make the module parameter for using mmio flips as tristate, the states being
'force CS flips', 'force mmio flips', 'driver discretion'.
Changed the logic for driver discretion (Chris)
v11: Minor code cleanup(better readability, fixing whitespace errors, using
lockdep to check mutex locked status in postpone_flip, removal of __must_check
in function definition) (Chris)
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
Signed-off-by: Akash Goel <akash.goel@intel.com>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk> # snb, ivb
[danvet: Fix up parameter alignement checkpatch spotted.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-06-02 16:47:17 +05:30
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-16 09:19:13 -07:00
|
|
|
static int intel_default_queue_flip(struct drm_device *dev,
|
|
|
|
|
struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_i915_gem_object *obj,
|
2015-05-29 17:43:48 +01:00
|
|
|
struct drm_i915_gem_request *req,
|
2013-07-22 18:49:58 -07:00
|
|
|
uint32_t flags)
|
2011-06-16 09:19:13 -07:00
|
|
|
{
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
static bool __intel_pageflip_stall_check(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);
|
|
|
|
|
struct intel_unpin_work *work = intel_crtc->unpin_work;
|
|
|
|
|
u32 addr;
|
|
|
|
|
|
|
|
|
|
if (atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE)
|
|
|
|
|
return true;
|
|
|
|
|
|
2015-08-12 13:08:22 +01:00
|
|
|
if (atomic_read(&work->pending) < INTEL_FLIP_PENDING)
|
|
|
|
|
return false;
|
|
|
|
|
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
if (!work->enable_stall_check)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (work->flip_ready_vblank == 0) {
|
2014-11-26 14:39:48 +01:00
|
|
|
if (work->flip_queued_req &&
|
|
|
|
|
!i915_gem_request_completed(work->flip_queued_req, true))
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
return false;
|
|
|
|
|
|
2015-02-13 21:03:45 +01:00
|
|
|
work->flip_ready_vblank = drm_crtc_vblank_count(crtc);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 21:03:45 +01:00
|
|
|
if (drm_crtc_vblank_count(crtc) - work->flip_ready_vblank < 3)
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* Potential stall - if we see that the flip has happened,
|
|
|
|
|
* assume a missed interrupt. */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4)
|
|
|
|
|
addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane)));
|
|
|
|
|
else
|
|
|
|
|
addr = I915_READ(DSPADDR(intel_crtc->plane));
|
|
|
|
|
|
|
|
|
|
/* There is a potential issue here with a false positive after a flip
|
|
|
|
|
* to the same address. We could address this by checking for a
|
|
|
|
|
* non-incrementing frame counter.
|
|
|
|
|
*/
|
|
|
|
|
return addr == work->gtt_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_check_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-04-07 16:20:31 +01:00
|
|
|
struct intel_unpin_work *work;
|
2014-09-15 14:55:23 +02:00
|
|
|
|
2015-03-06 15:34:26 +00:00
|
|
|
WARN_ON(!in_interrupt());
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
|
|
|
|
|
if (crtc == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-09-15 14:55:23 +02:00
|
|
|
spin_lock(&dev->event_lock);
|
2015-04-07 16:20:31 +01:00
|
|
|
work = intel_crtc->unpin_work;
|
|
|
|
|
if (work != NULL && __intel_pageflip_stall_check(dev, crtc)) {
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n",
|
2015-04-07 16:20:31 +01:00
|
|
|
work->flip_queued_vblank, drm_vblank_count(dev, pipe));
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
page_flip_completed(intel_crtc);
|
2015-04-07 16:20:31 +01:00
|
|
|
work = NULL;
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
}
|
2015-04-07 16:20:31 +01:00
|
|
|
if (work != NULL &&
|
|
|
|
|
drm_vblank_count(dev, pipe) - work->flip_queued_vblank > 1)
|
|
|
|
|
intel_queue_rps_boost_for_request(dev, work->flip_queued_req);
|
2014-09-15 14:55:23 +02:00
|
|
|
spin_unlock(&dev->event_lock);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
}
|
|
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_framebuffer *fb,
|
2013-07-22 18:49:58 -07:00
|
|
|
struct drm_pending_vblank_event *event,
|
|
|
|
|
uint32_t page_flip_flags)
|
2009-11-18 11:25:18 -05:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-04-01 15:22:40 -07:00
|
|
|
struct drm_framebuffer *old_fb = crtc->primary->fb;
|
2014-07-08 07:50:07 -07:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
2009-11-18 11:25:18 -05:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2014-12-01 15:40:11 -08:00
|
|
|
struct drm_plane *primary = crtc->primary;
|
2014-06-18 23:28:09 +02:00
|
|
|
enum pipe pipe = intel_crtc->pipe;
|
2009-11-18 11:25:18 -05:00
|
|
|
struct intel_unpin_work *work;
|
2014-05-22 14:13:33 +01:00
|
|
|
struct intel_engine_cs *ring;
|
2015-04-07 16:20:26 +01:00
|
|
|
bool mmio_flip;
|
2015-06-18 13:14:56 +01:00
|
|
|
struct drm_i915_gem_request *request = NULL;
|
2010-08-08 10:15:59 +01:00
|
|
|
int ret;
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2014-07-08 07:50:07 -07:00
|
|
|
/*
|
|
|
|
|
* drm_mode_page_flip_ioctl() should already catch this, but double
|
|
|
|
|
* check to be safe. In the future we may enable pageflipping from
|
|
|
|
|
* a disabled primary plane.
|
|
|
|
|
*/
|
|
|
|
|
if (WARN_ON(intel_fb_obj(old_fb) == NULL))
|
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
2012-05-24 21:08:59 +03:00
|
|
|
/* Can't change pixel format via MI display flips. */
|
2014-04-01 15:22:40 -07:00
|
|
|
if (fb->pixel_format != crtc->primary->fb->pixel_format)
|
2012-05-24 21:08:59 +03:00
|
|
|
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 &&
|
2014-04-01 15:22:40 -07:00
|
|
|
(fb->offsets[0] != crtc->primary->fb->offsets[0] ||
|
|
|
|
|
fb->pitches[0] != crtc->primary->fb->pitches[0]))
|
2012-05-24 21:08:59 +03:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
2014-02-20 09:26:13 +00:00
|
|
|
if (i915_terminally_wedged(&dev_priv->gpu_error))
|
|
|
|
|
goto out_hang;
|
|
|
|
|
|
2013-09-19 12:18:32 +02:00
|
|
|
work = kzalloc(sizeof(*work), GFP_KERNEL);
|
2009-11-18 11:25:18 -05:00
|
|
|
if (work == NULL)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
work->event = event;
|
2012-11-01 09:26:26 +00:00
|
|
|
work->crtc = crtc;
|
2015-02-02 15:44:15 +00:00
|
|
|
work->old_fb = old_fb;
|
2009-11-18 11:25:18 -05:00
|
|
|
INIT_WORK(&work->work, intel_unpin_work_fn);
|
|
|
|
|
|
2014-05-15 15:33:46 +02:00
|
|
|
ret = drm_crtc_vblank_get(crtc);
|
2011-08-29 09:45:28 -07:00
|
|
|
if (ret)
|
|
|
|
|
goto free_work;
|
|
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
/* We borrow the event spin lock for protecting unpin_work */
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2009-11-18 11:25:18 -05:00
|
|
|
if (intel_crtc->unpin_work) {
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
/* Before declaring the flip queue wedged, check if
|
|
|
|
|
* the hardware completed the operation behind our backs.
|
|
|
|
|
*/
|
|
|
|
|
if (__intel_pageflip_stall_check(dev, crtc)) {
|
|
|
|
|
DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n");
|
|
|
|
|
page_flip_completed(intel_crtc);
|
|
|
|
|
} else {
|
|
|
|
|
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2010-05-27 13:18:13 +01:00
|
|
|
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
drm_crtc_vblank_put(crtc);
|
|
|
|
|
kfree(work);
|
|
|
|
|
return -EBUSY;
|
|
|
|
|
}
|
2009-11-18 11:25:18 -05:00
|
|
|
}
|
|
|
|
|
intel_crtc->unpin_work = work;
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2012-11-01 09:26:26 +00:00
|
|
|
if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
|
|
|
|
|
flush_workqueue(dev_priv->wq);
|
|
|
|
|
|
2010-02-10 15:09:44 -08:00
|
|
|
/* Reference the objects for the scheduled work. */
|
2015-02-02 15:44:15 +00:00
|
|
|
drm_framebuffer_reference(work->old_fb);
|
2010-11-08 19:18:58 +00:00
|
|
|
drm_gem_object_reference(&obj->base);
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2014-04-01 15:22:40 -07:00
|
|
|
crtc->primary->fb = fb;
|
2015-02-03 13:10:04 -08:00
|
|
|
update_state_fb(crtc->primary);
|
2015-01-30 16:22:36 -08:00
|
|
|
|
2010-10-27 12:45:26 +01:00
|
|
|
work->pending_flip_obj = obj;
|
|
|
|
|
|
2015-02-16 14:31:49 +00:00
|
|
|
ret = i915_mutex_lock_interruptible(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
2012-11-01 09:26:26 +00:00
|
|
|
atomic_inc(&intel_crtc->unpin_work_count);
|
2013-01-29 18:13:34 +02:00
|
|
|
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
2010-10-27 12:45:26 +01:00
|
|
|
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
|
2015-09-18 20:03:42 +03:00
|
|
|
work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
|
drm/i915: Fix mmio vs. CS flip race on ILK+
Starting from ILK, mmio flips also cause a flip done interrupt to be
signalled. This means if we first do a set_base and follow it
immediately with the CS flip, we might mistake the flip done interrupt
caused by the set_base as the flip done interrupt caused by the CS
flip.
The hardware has a flip counter which increments every time a mmio or
CS flip is issued. It basically counts the number of DSPSURF register
writes. This means we can sample the counter before we put the CS
flip into the ring, and then when we get a flip done interrupt we can
check whether the CS flip has actually performed the surface address
update, or if the interrupt was caused by a previous but yet
unfinished mmio flip.
Even with the flip counter we still have a race condition of the CS flip
base address update happens after the mmio flip done interrupt was
raised but not yet processed by the driver. When the interrupt is
eventually processed, the flip counter will already indicate that the
CS flip has been executed, but it would not actually complete until the
next start of vblank. We can use the DSPSURFLIVE register to check
whether the hardware is actually scanning out of the buffer we expect,
or if we managed hit this race window.
This covers all the cases where the CS flip actually changes the base
address. If the base address remains unchanged, we might still complete
the CS flip before it has actually completed. But since the address
didn't change anyway, the premature flip completion can't result in
userspace overwriting data that's still being scanned out.
CTG already has the flip counter and DSPSURFLIVE registers, and
although the flip done interrupt is still limited to CS flips alone,
the code now also checks the flip counter on CTG as well.
v2: s/dspsurf/gtt_offset/ (Chris)
Testcase: igt/kms_mmio_vs_cs_flip/setcrtc_vs_cs_flip
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73027
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add g4x_ prefix to flip_count_after_eq.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-04-15 21:41:34 +03:00
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2014-04-15 21:41:38 +03:00
|
|
|
ring = &dev_priv->ring[BCS];
|
2015-02-02 15:44:15 +00:00
|
|
|
if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
|
2014-07-08 10:40:30 +01:00
|
|
|
/* vlv: DISPLAY_FLIP fails to change tiling */
|
|
|
|
|
ring = NULL;
|
2014-12-27 09:48:28 +00:00
|
|
|
} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
|
2014-07-08 10:40:29 +01:00
|
|
|
ring = &dev_priv->ring[BCS];
|
2014-04-15 21:41:38 +03:00
|
|
|
} else if (INTEL_INFO(dev)->gen >= 7) {
|
2015-04-27 13:41:17 +01:00
|
|
|
ring = i915_gem_request_get_ring(obj->last_write_req);
|
2014-04-15 21:41:38 +03:00
|
|
|
if (ring == NULL || ring->id != RCS)
|
|
|
|
|
ring = &dev_priv->ring[BCS];
|
|
|
|
|
} else {
|
|
|
|
|
ring = &dev_priv->ring[RCS];
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-07 16:20:26 +01:00
|
|
|
mmio_flip = use_mmio_flip(ring, obj);
|
|
|
|
|
|
|
|
|
|
/* When using CS flips, we want to emit semaphores between rings.
|
|
|
|
|
* However, when using mmio flips we will create a task to do the
|
|
|
|
|
* synchronisation, so all we want here is to pin the framebuffer
|
|
|
|
|
* into the display plane and skip any waits.
|
|
|
|
|
*/
|
2015-08-18 13:40:06 +02:00
|
|
|
if (!mmio_flip) {
|
|
|
|
|
ret = i915_gem_object_sync(obj, ring, &request);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto cleanup_pending;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-23 11:10:34 +00:00
|
|
|
ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
|
2015-08-18 13:40:06 +02:00
|
|
|
crtc->primary->state);
|
2011-06-16 09:19:13 -07:00
|
|
|
if (ret)
|
|
|
|
|
goto cleanup_pending;
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2015-09-21 10:45:35 +01:00
|
|
|
work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
|
|
|
|
|
obj, 0);
|
|
|
|
|
work->gtt_offset += intel_crtc->dspaddr_offset;
|
2014-04-15 21:41:38 +03:00
|
|
|
|
2015-04-07 16:20:26 +01:00
|
|
|
if (mmio_flip) {
|
2015-10-20 16:20:21 +01:00
|
|
|
ret = intel_queue_mmio_flip(dev, crtc, obj);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
if (ret)
|
|
|
|
|
goto cleanup_unpin;
|
|
|
|
|
|
2014-11-24 18:49:37 +00:00
|
|
|
i915_gem_request_assign(&work->flip_queued_req,
|
|
|
|
|
obj->last_write_req);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
} else {
|
2015-05-29 17:43:48 +01:00
|
|
|
if (!request) {
|
|
|
|
|
ret = i915_gem_request_alloc(ring, ring->default_context, &request);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto cleanup_unpin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request,
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
page_flip_flags);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto cleanup_unpin;
|
|
|
|
|
|
2015-05-29 17:43:48 +01:00
|
|
|
i915_gem_request_assign(&work->flip_queued_req, request);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-18 13:14:56 +01:00
|
|
|
if (request)
|
2015-05-29 17:43:49 +01:00
|
|
|
i915_add_request_no_flush(request);
|
2015-06-18 13:14:56 +01:00
|
|
|
|
2015-02-13 21:03:45 +01:00
|
|
|
work->flip_queued_vblank = drm_crtc_vblank_count(crtc);
|
drm/i915: Check for a stalled page flip after each vblank
Long ago, back in the racy haydays of 915gm interrupt handling, page
flips would occasionally go astray and leave the hardware stuck, and the
display not updating. This annoyed people who relied on their systems
being able to display continuously updating information 24/7, and so
some code to detect when the driver missed the page flip completion
signal was added. Until recently, it was presumed that the interrupt
handling was now flawless, but once again Simon Farnsworth has found a
system whose display will stall. Reinstate the pageflip stall detection,
which works by checking to see if the hardware has been updated to the
new framebuffer address following each vblank. If the hardware is
scanning out from the new framebuffer, but we still think the flip is
pending, then we kick our driver into submision.
This is a continuation of the effort started with
commit 4e5359cd053bfb7d8dabe4a63624a5726848ffbc
Author: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Date: Wed Sep 1 17:47:52 2010 +0100
drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
This now includes a belt-and-braces approach to make sure the driver
(or the hardware) doesn't miss an interrupt and cause us to stop
updating the display should the unthinkable happen and the pageflip fail - i.e.
that the user is able to continue submitting flips.
v2: Cleanup, refactor, and rename
v3: Only start counting vblanks after the flip command has been seen by
the hardware.
v4: Record the seqno after we touch the ring, or else there may be no
seqno allocated yet.
v5: Rebase on mmio-flip.
v6: Rebase, rebase.
Reported-by: Simon Farnsworth <simon@farnz.org.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> [v4]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-09-05 07:13:24 +01:00
|
|
|
work->enable_stall_check = true;
|
2014-04-15 21:41:38 +03:00
|
|
|
|
2015-02-02 15:44:15 +00:00
|
|
|
i915_gem_track_fb(intel_fb_obj(work->old_fb), obj,
|
2015-06-24 21:59:34 +03:00
|
|
|
to_intel_plane(primary)->frontbuffer_bit);
|
2015-07-02 19:25:13 -03:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2014-06-18 23:28:09 +02:00
|
|
|
|
2015-10-15 10:44:46 -03:00
|
|
|
intel_fbc_deactivate(intel_crtc);
|
2015-06-24 21:59:34 +03:00
|
|
|
intel_frontbuffer_flip_prepare(dev,
|
|
|
|
|
to_intel_plane(primary)->frontbuffer_bit);
|
2009-11-18 11:25:18 -05:00
|
|
|
|
2010-07-01 16:48:37 -07:00
|
|
|
trace_i915_flip_request(intel_crtc->plane, obj);
|
|
|
|
|
|
2009-11-18 11:25:18 -05:00
|
|
|
return 0;
|
2010-06-07 14:03:04 +01:00
|
|
|
|
2014-04-15 21:41:38 +03:00
|
|
|
cleanup_unpin:
|
2015-03-23 11:10:34 +00:00
|
|
|
intel_unpin_fb_obj(fb, crtc->primary->state);
|
2011-06-16 09:19:13 -07:00
|
|
|
cleanup_pending:
|
2015-06-18 13:14:56 +01:00
|
|
|
if (request)
|
|
|
|
|
i915_gem_request_cancel(request);
|
2012-11-01 09:26:26 +00:00
|
|
|
atomic_dec(&intel_crtc->unpin_work_count);
|
2015-02-16 14:31:49 +00:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
cleanup:
|
2014-04-01 15:22:40 -07:00
|
|
|
crtc->primary->fb = old_fb;
|
2015-02-03 13:10:04 -08:00
|
|
|
update_state_fb(crtc->primary);
|
2015-02-16 14:31:49 +00:00
|
|
|
|
|
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
2015-02-02 15:44:15 +00:00
|
|
|
drm_framebuffer_unreference(work->old_fb);
|
2010-06-07 14:03:04 +01:00
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2010-06-07 14:03:04 +01:00
|
|
|
intel_crtc->unpin_work = NULL;
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2010-06-07 14:03:04 +01:00
|
|
|
|
2014-05-15 15:33:46 +02:00
|
|
|
drm_crtc_vblank_put(crtc);
|
2011-08-29 09:45:28 -07:00
|
|
|
free_work:
|
2010-06-07 14:03:04 +01:00
|
|
|
kfree(work);
|
|
|
|
|
|
2014-02-20 09:26:13 +00:00
|
|
|
if (ret == -EIO) {
|
2015-06-12 11:15:40 +02:00
|
|
|
struct drm_atomic_state *state;
|
|
|
|
|
struct drm_plane_state *plane_state;
|
|
|
|
|
|
2014-02-20 09:26:13 +00:00
|
|
|
out_hang:
|
2015-06-12 11:15:40 +02:00
|
|
|
state = drm_atomic_state_alloc(dev);
|
|
|
|
|
if (!state)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
|
|
|
|
|
|
|
|
|
retry:
|
|
|
|
|
plane_state = drm_atomic_get_plane_state(state, primary);
|
|
|
|
|
ret = PTR_ERR_OR_ZERO(plane_state);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
drm_atomic_set_fb_for_plane(plane_state, fb);
|
|
|
|
|
|
|
|
|
|
ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
|
|
|
|
|
if (!ret)
|
|
|
|
|
ret = drm_atomic_commit(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == -EDEADLK) {
|
|
|
|
|
drm_modeset_backoff(state->acquire_ctx);
|
|
|
|
|
drm_atomic_state_clear(state);
|
|
|
|
|
goto retry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
drm_atomic_state_free(state);
|
|
|
|
|
|
2014-09-07 16:51:12 +01:00
|
|
|
if (ret == 0 && event) {
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2014-06-18 23:28:09 +02:00
|
|
|
drm_send_vblank_event(dev, pipe, event);
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2014-09-07 16:51:12 +01:00
|
|
|
}
|
2014-02-20 09:26:13 +00:00
|
|
|
}
|
2010-06-07 14:03:04 +01:00
|
|
|
return ret;
|
2009-11-18 11:25:18 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:44 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* intel_wm_need_update - Check whether watermarks need updating
|
|
|
|
|
* @plane: drm plane
|
|
|
|
|
* @state: new plane state
|
|
|
|
|
*
|
|
|
|
|
* Check current plane state versus the new one to determine whether
|
|
|
|
|
* watermarks need to be recalculated.
|
|
|
|
|
*
|
|
|
|
|
* Returns true or false.
|
|
|
|
|
*/
|
|
|
|
|
static bool intel_wm_need_update(struct drm_plane *plane,
|
|
|
|
|
struct drm_plane_state *state)
|
|
|
|
|
{
|
2015-09-24 15:53:12 -07:00
|
|
|
struct intel_plane_state *new = to_intel_plane_state(state);
|
|
|
|
|
struct intel_plane_state *cur = to_intel_plane_state(plane->state);
|
|
|
|
|
|
|
|
|
|
/* Update watermarks on tiling or size changes. */
|
2015-12-03 13:49:13 +01:00
|
|
|
if (new->visible != cur->visible)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (!cur->base.fb || !new->base.fb)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
|
|
|
|
|
cur->base.rotation != new->base.rotation ||
|
2015-09-24 15:53:12 -07:00
|
|
|
drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
|
|
|
|
|
drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
|
|
|
|
|
drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
|
|
|
|
|
drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
|
2015-10-09 18:22:43 -03:00
|
|
|
return true;
|
2015-09-24 15:53:12 -07:00
|
|
|
|
2015-10-09 18:22:43 -03:00
|
|
|
return false;
|
2015-09-24 15:53:12 -07:00
|
|
|
}
|
|
|
|
|
|
2015-09-24 15:53:12 -07:00
|
|
|
static bool needs_scaling(struct intel_plane_state *state)
|
|
|
|
|
{
|
|
|
|
|
int src_w = drm_rect_width(&state->src) >> 16;
|
|
|
|
|
int src_h = drm_rect_height(&state->src) >> 16;
|
|
|
|
|
int dst_w = drm_rect_width(&state->dst);
|
|
|
|
|
int dst_h = drm_rect_height(&state->dst);
|
|
|
|
|
|
|
|
|
|
return (src_w != dst_w || src_h != dst_h);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:44 +02:00
|
|
|
int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|
|
|
|
struct drm_plane_state *plane_state)
|
|
|
|
|
{
|
2015-11-19 16:07:14 +01:00
|
|
|
struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
|
2015-06-15 12:33:44 +02:00
|
|
|
struct drm_crtc *crtc = crtc_state->crtc;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
struct drm_plane *plane = plane_state->plane;
|
|
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct intel_plane_state *old_plane_state =
|
|
|
|
|
to_intel_plane_state(plane->state);
|
|
|
|
|
int idx = intel_crtc->base.base.id, ret;
|
|
|
|
|
int i = drm_plane_index(plane);
|
|
|
|
|
bool mode_changed = needs_modeset(crtc_state);
|
|
|
|
|
bool was_crtc_enabled = crtc->state->active;
|
|
|
|
|
bool is_crtc_enabled = crtc_state->active;
|
|
|
|
|
bool turn_off, turn_on, visible, was_visible;
|
|
|
|
|
struct drm_framebuffer *fb = plane_state->fb;
|
|
|
|
|
|
|
|
|
|
if (crtc_state && INTEL_INFO(dev)->gen >= 9 &&
|
|
|
|
|
plane->type != DRM_PLANE_TYPE_CURSOR) {
|
|
|
|
|
ret = skl_update_scaler_plane(
|
|
|
|
|
to_intel_crtc_state(crtc_state),
|
|
|
|
|
to_intel_plane_state(plane_state));
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
was_visible = old_plane_state->visible;
|
|
|
|
|
visible = to_intel_plane_state(plane_state)->visible;
|
|
|
|
|
|
|
|
|
|
if (!was_crtc_enabled && WARN_ON(was_visible))
|
|
|
|
|
was_visible = false;
|
|
|
|
|
|
2015-12-03 14:31:07 +01:00
|
|
|
/*
|
|
|
|
|
* Visibility is calculated as if the crtc was on, but
|
|
|
|
|
* after scaler setup everything depends on it being off
|
|
|
|
|
* when the crtc isn't active.
|
|
|
|
|
*/
|
|
|
|
|
if (!is_crtc_enabled)
|
|
|
|
|
to_intel_plane_state(plane_state)->visible = visible = false;
|
2015-06-15 12:33:44 +02:00
|
|
|
|
|
|
|
|
if (!was_visible && !visible)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
turn_off = was_visible && (!visible || mode_changed);
|
|
|
|
|
turn_on = visible && (!was_visible || mode_changed);
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_ATOMIC("[CRTC:%i] has [PLANE:%i] with fb %i\n", idx,
|
|
|
|
|
plane->base.id, fb ? fb->base.id : -1);
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_ATOMIC("[PLANE:%i] visible %i -> %i, off %i, on %i, ms %i\n",
|
|
|
|
|
plane->base.id, was_visible, visible,
|
|
|
|
|
turn_off, turn_on, mode_changed);
|
|
|
|
|
|
2015-12-03 13:49:13 +01:00
|
|
|
if (turn_on || turn_off) {
|
|
|
|
|
pipe_config->wm_changed = true;
|
|
|
|
|
|
2015-06-24 22:00:07 +03:00
|
|
|
/* must disable cxsr around plane enable/disable */
|
|
|
|
|
if (plane->type != DRM_PLANE_TYPE_CURSOR) {
|
|
|
|
|
if (is_crtc_enabled)
|
|
|
|
|
intel_crtc->atomic.wait_vblank = true;
|
2015-11-19 16:07:14 +01:00
|
|
|
pipe_config->disable_cxsr = true;
|
2015-06-24 22:00:07 +03:00
|
|
|
}
|
|
|
|
|
} else if (intel_wm_need_update(plane, plane_state)) {
|
2015-12-03 13:49:13 +01:00
|
|
|
pipe_config->wm_changed = true;
|
2015-06-24 22:00:07 +03:00
|
|
|
}
|
2015-06-15 12:33:44 +02:00
|
|
|
|
2016-01-06 11:34:30 -08:00
|
|
|
/* Pre-gen9 platforms need two-step watermark updates */
|
|
|
|
|
if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 &&
|
|
|
|
|
dev_priv->display.optimize_watermarks)
|
|
|
|
|
to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
|
|
|
|
|
|
2015-08-24 16:38:23 -07:00
|
|
|
if (visible || was_visible)
|
2015-06-24 21:59:34 +03:00
|
|
|
intel_crtc->atomic.fb_bits |=
|
|
|
|
|
to_intel_plane(plane)->frontbuffer_bit;
|
|
|
|
|
|
2015-06-15 12:33:44 +02:00
|
|
|
switch (plane->type) {
|
|
|
|
|
case DRM_PLANE_TYPE_PRIMARY:
|
|
|
|
|
intel_crtc->atomic.pre_disable_primary = turn_off;
|
|
|
|
|
intel_crtc->atomic.post_enable_primary = turn_on;
|
|
|
|
|
|
2015-06-26 13:55:54 -07:00
|
|
|
if (turn_off) {
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: Actually if we will still have any other
|
|
|
|
|
* plane enabled on the pipe we could let IPS enabled
|
|
|
|
|
* still, but for now lets consider that when we make
|
|
|
|
|
* primary invisible by setting DSPCNTR to 0 on
|
|
|
|
|
* update_primary_plane function IPS needs to be
|
|
|
|
|
* disable.
|
|
|
|
|
*/
|
|
|
|
|
intel_crtc->atomic.disable_ips = true;
|
|
|
|
|
|
2015-06-15 12:33:44 +02:00
|
|
|
intel_crtc->atomic.disable_fbc = true;
|
2015-06-26 13:55:54 -07:00
|
|
|
}
|
2015-06-15 12:33:44 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FBC does not work on some platforms for rotated
|
|
|
|
|
* planes, so disable it when rotation is not 0 and
|
|
|
|
|
* update it when rotation is set back to 0.
|
|
|
|
|
*
|
|
|
|
|
* FIXME: This is redundant with the fbc update done in
|
|
|
|
|
* the primary plane enable function except that that
|
|
|
|
|
* one is done too late. We eventually need to unify
|
|
|
|
|
* this.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (visible &&
|
|
|
|
|
INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
|
|
|
|
|
dev_priv->fbc.crtc == intel_crtc &&
|
|
|
|
|
plane_state->rotation != BIT(DRM_ROTATE_0))
|
|
|
|
|
intel_crtc->atomic.disable_fbc = true;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* BDW signals flip done immediately if the plane
|
|
|
|
|
* is disabled, even if the plane enable is already
|
|
|
|
|
* armed to occur at the next vblank :(
|
|
|
|
|
*/
|
|
|
|
|
if (turn_on && IS_BROADWELL(dev))
|
|
|
|
|
intel_crtc->atomic.wait_vblank = true;
|
|
|
|
|
|
|
|
|
|
intel_crtc->atomic.update_fbc |= visible || mode_changed;
|
|
|
|
|
break;
|
|
|
|
|
case DRM_PLANE_TYPE_CURSOR:
|
|
|
|
|
break;
|
|
|
|
|
case DRM_PLANE_TYPE_OVERLAY:
|
2015-09-24 15:53:12 -07:00
|
|
|
/*
|
|
|
|
|
* WaCxSRDisabledForSpriteScaling:ivb
|
|
|
|
|
*
|
|
|
|
|
* cstate->update_wm was already set above, so this flag will
|
|
|
|
|
* take effect when we commit and program watermarks.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_IVYBRIDGE(dev) &&
|
|
|
|
|
needs_scaling(to_intel_plane_state(plane_state)) &&
|
|
|
|
|
!needs_scaling(old_plane_state)) {
|
|
|
|
|
to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
|
|
|
|
|
} else if (turn_off && !mode_changed) {
|
2015-06-15 12:33:44 +02:00
|
|
|
intel_crtc->atomic.wait_vblank = true;
|
|
|
|
|
intel_crtc->atomic.update_sprite_watermarks |=
|
|
|
|
|
1 << i;
|
|
|
|
|
}
|
2015-09-24 15:53:12 -07:00
|
|
|
|
|
|
|
|
break;
|
2015-06-15 12:33:44 +02:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:40 +02:00
|
|
|
static bool encoders_cloneable(const struct intel_encoder *a,
|
|
|
|
|
const struct intel_encoder *b)
|
|
|
|
|
{
|
|
|
|
|
/* masks could be asymmetric, so check both ways */
|
|
|
|
|
return a == b || (a->cloneable & (1 << b->type) &&
|
|
|
|
|
b->cloneable & (1 << a->type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool check_single_encoder_cloning(struct drm_atomic_state *state,
|
|
|
|
|
struct intel_crtc *crtc,
|
|
|
|
|
struct intel_encoder *encoder)
|
|
|
|
|
{
|
|
|
|
|
struct intel_encoder *source_encoder;
|
|
|
|
|
struct drm_connector *connector;
|
|
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
|
|
|
|
if (connector_state->crtc != &crtc->base)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
source_encoder =
|
|
|
|
|
to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
if (!encoders_cloneable(encoder, source_encoder))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool check_encoder_cloning(struct drm_atomic_state *state,
|
|
|
|
|
struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
struct drm_connector *connector;
|
|
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
|
|
|
|
if (connector_state->crtc != &crtc->base)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
if (!check_single_encoder_cloning(state, crtc, encoder))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_crtc_atomic_check(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_crtc_state *crtc_state)
|
|
|
|
|
{
|
2015-06-15 12:33:41 +02:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2015-06-15 12:33:42 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-06-15 12:33:40 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-06-15 12:33:41 +02:00
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc_state);
|
2015-06-15 12:33:40 +02:00
|
|
|
struct drm_atomic_state *state = crtc_state->state;
|
2015-08-05 12:37:05 +02:00
|
|
|
int ret;
|
2015-06-15 12:33:40 +02:00
|
|
|
bool mode_changed = needs_modeset(crtc_state);
|
|
|
|
|
|
|
|
|
|
if (mode_changed && !check_encoder_cloning(state, intel_crtc)) {
|
|
|
|
|
DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-24 22:00:07 +03:00
|
|
|
if (mode_changed && !crtc_state->active)
|
2015-12-03 13:49:13 +01:00
|
|
|
pipe_config->wm_changed = true;
|
2015-06-15 12:33:53 +02:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
if (mode_changed && crtc_state->enable &&
|
|
|
|
|
dev_priv->display.crtc_compute_clock &&
|
|
|
|
|
!WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
|
|
|
|
|
ret = dev_priv->display.crtc_compute_clock(intel_crtc,
|
|
|
|
|
pipe_config);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:15 +02:00
|
|
|
ret = 0;
|
2015-09-24 15:53:16 -07:00
|
|
|
if (dev_priv->display.compute_pipe_wm) {
|
|
|
|
|
ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
|
2016-01-06 11:34:30 -08:00
|
|
|
if (ret) {
|
|
|
|
|
DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dev_priv->display.compute_intermediate_wm &&
|
|
|
|
|
!to_intel_atomic_state(state)->skip_intermediate_wm) {
|
|
|
|
|
if (WARN_ON(!dev_priv->display.compute_pipe_wm))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Calculate 'intermediate' watermarks that satisfy both the
|
|
|
|
|
* old state and the new state. We can program these
|
|
|
|
|
* immediately.
|
|
|
|
|
*/
|
|
|
|
|
ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
|
|
|
|
|
intel_crtc,
|
|
|
|
|
pipe_config);
|
|
|
|
|
if (ret) {
|
|
|
|
|
DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
|
2015-09-24 15:53:16 -07:00
|
|
|
return ret;
|
2016-01-06 11:34:30 -08:00
|
|
|
}
|
2015-09-24 15:53:16 -07:00
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:15 +02:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
if (mode_changed)
|
|
|
|
|
ret = skl_update_scaler_crtc(pipe_config);
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
ret = intel_atomic_setup_scalers(dev, intel_crtc,
|
|
|
|
|
pipe_config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2015-06-15 12:33:40 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 11:26:56 +03:00
|
|
|
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
|
2011-04-12 18:06:51 +01:00
|
|
|
.mode_set_base_atomic = intel_pipe_set_base_atomic,
|
|
|
|
|
.load_lut = intel_crtc_load_lut,
|
2014-12-23 10:41:52 -08:00
|
|
|
.atomic_begin = intel_begin_crtc_commit,
|
|
|
|
|
.atomic_flush = intel_finish_crtc_commit,
|
2015-06-15 12:33:40 +02:00
|
|
|
.atomic_check = intel_crtc_atomic_check,
|
2011-04-12 18:06:51 +01:00
|
|
|
};
|
|
|
|
|
|
2015-03-20 16:18:05 +02:00
|
|
|
static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct intel_connector *connector;
|
|
|
|
|
|
|
|
|
|
for_each_intel_connector(dev, connector) {
|
|
|
|
|
if (connector->base.encoder) {
|
|
|
|
|
connector->base.state->best_encoder =
|
|
|
|
|
connector->base.encoder;
|
|
|
|
|
connector->base.state->crtc =
|
|
|
|
|
connector->base.encoder->crtc;
|
|
|
|
|
} else {
|
|
|
|
|
connector->base.state->best_encoder = NULL;
|
|
|
|
|
connector->base.state->crtc = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-02 13:26:23 +02:00
|
|
|
static void
|
2014-05-18 02:24:50 +02:00
|
|
|
connected_sink_compute_bpp(struct intel_connector *connector,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2013-06-02 13:26:23 +02:00
|
|
|
{
|
|
|
|
|
int bpp = pipe_config->pipe_bpp;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
|
|
|
|
|
connector->base.base.id,
|
2014-06-03 14:56:17 +03:00
|
|
|
connector->base.name);
|
2013-06-02 13:26:23 +02:00
|
|
|
|
|
|
|
|
/* 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 00:44:58 +01:00
|
|
|
static int
|
2013-06-02 13:26:23 +02:00
|
|
|
compute_baseline_pipe_bpp(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *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 00:44:58 +01:00
|
|
|
{
|
2013-06-02 13:26:23 +02:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
2015-03-20 16:18:09 +02:00
|
|
|
struct drm_atomic_state *state;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
|
|
|
|
struct drm_connector_state *connector_state;
|
2015-03-20 16:18:09 +02:00
|
|
|
int bpp, i;
|
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 00:44:58 +01:00
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
|
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 00:44:58 +01:00
|
|
|
bpp = 10*3;
|
2015-04-10 16:22:37 +02:00
|
|
|
else if (INTEL_INFO(dev)->gen >= 5)
|
|
|
|
|
bpp = 12*3;
|
|
|
|
|
else
|
|
|
|
|
bpp = 8*3;
|
|
|
|
|
|
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 00:44:58 +01:00
|
|
|
|
|
|
|
|
pipe_config->pipe_bpp = bpp;
|
|
|
|
|
|
2015-03-20 16:18:09 +02:00
|
|
|
state = pipe_config->base.state;
|
|
|
|
|
|
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 00:44:58 +01:00
|
|
|
/* Clamp display bpp to EDID value */
|
2015-04-21 17:12:59 +03:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
|
|
|
|
if (connector_state->crtc != &crtc->base)
|
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 00:44:58 +01:00
|
|
|
continue;
|
|
|
|
|
|
2015-04-21 17:12:59 +03:00
|
|
|
connected_sink_compute_bpp(to_intel_connector(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 00:44:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bpp;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 14:53:58 +02:00
|
|
|
static void intel_dump_crtc_timings(const struct drm_display_mode *mode)
|
|
|
|
|
{
|
|
|
|
|
DRM_DEBUG_KMS("crtc timings: %d %d %d %d %d %d %d %d %d, "
|
|
|
|
|
"type: 0x%x flags: 0x%x\n",
|
2013-09-25 16:45:36 +01:00
|
|
|
mode->crtc_clock,
|
2013-09-19 14:53:58 +02:00
|
|
|
mode->crtc_hdisplay, mode->crtc_hsync_start,
|
|
|
|
|
mode->crtc_hsync_end, mode->crtc_htotal,
|
|
|
|
|
mode->crtc_vdisplay, mode->crtc_vsync_start,
|
|
|
|
|
mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 12:05:54 +02:00
|
|
|
static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *pipe_config,
|
2013-05-28 12:05:54 +02:00
|
|
|
const char *context)
|
|
|
|
|
{
|
2015-04-07 15:28:40 -07:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_plane *plane;
|
|
|
|
|
struct intel_plane *intel_plane;
|
|
|
|
|
struct intel_plane_state *state;
|
|
|
|
|
struct drm_framebuffer *fb;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id,
|
|
|
|
|
context, pipe_config, pipe_name(crtc->pipe));
|
2013-05-28 12:05:54 +02:00
|
|
|
|
|
|
|
|
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);
|
2015-07-06 16:39:15 +03:00
|
|
|
DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
|
2013-09-10 17:02:54 +03:00
|
|
|
pipe_config->has_dp_encoder,
|
2015-07-06 16:39:15 +03:00
|
|
|
pipe_config->lane_count,
|
2013-09-10 17:02:54 +03:00
|
|
|
pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n,
|
|
|
|
|
pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n,
|
|
|
|
|
pipe_config->dp_m_n.tu);
|
2014-08-05 07:51:23 -07:00
|
|
|
|
2015-07-06 16:39:15 +03:00
|
|
|
DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
|
2014-08-05 07:51:23 -07:00
|
|
|
pipe_config->has_dp_encoder,
|
2015-07-06 16:39:15 +03:00
|
|
|
pipe_config->lane_count,
|
2014-08-05 07:51:23 -07:00
|
|
|
pipe_config->dp_m2_n2.gmch_m,
|
|
|
|
|
pipe_config->dp_m2_n2.gmch_n,
|
|
|
|
|
pipe_config->dp_m2_n2.link_m,
|
|
|
|
|
pipe_config->dp_m2_n2.link_n,
|
|
|
|
|
pipe_config->dp_m2_n2.tu);
|
|
|
|
|
|
2014-11-20 16:10:28 +01:00
|
|
|
DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
|
|
|
|
|
pipe_config->has_audio,
|
|
|
|
|
pipe_config->has_infoframe);
|
|
|
|
|
|
2013-05-28 12:05:54 +02:00
|
|
|
DRM_DEBUG_KMS("requested mode:\n");
|
2015-01-15 14:55:22 +02:00
|
|
|
drm_mode_debug_printmodeline(&pipe_config->base.mode);
|
2013-05-28 12:05:54 +02:00
|
|
|
DRM_DEBUG_KMS("adjusted mode:\n");
|
2015-01-15 14:55:22 +02:00
|
|
|
drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
|
|
|
|
|
intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
|
2013-09-06 23:29:08 +03:00
|
|
|
DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
|
2013-09-04 18:25:28 +03:00
|
|
|
DRM_DEBUG_KMS("pipe src size: %dx%d\n",
|
|
|
|
|
pipe_config->pipe_src_w, pipe_config->pipe_src_h);
|
2015-05-13 16:51:08 +01:00
|
|
|
DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
|
|
|
|
|
crtc->num_scalers,
|
|
|
|
|
pipe_config->scaler_state.scaler_users,
|
|
|
|
|
pipe_config->scaler_state.scaler_id);
|
2013-05-28 12:05:54 +02:00
|
|
|
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);
|
2013-08-27 17:04:17 +01:00
|
|
|
DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
|
2013-05-28 12:05:54 +02:00
|
|
|
pipe_config->pch_pfit.pos,
|
2013-08-27 17:04:17 +01:00
|
|
|
pipe_config->pch_pfit.size,
|
|
|
|
|
pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
|
2013-05-31 16:33:22 -03:00
|
|
|
DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
|
2013-09-04 18:30:02 +03:00
|
|
|
DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
|
2015-04-07 15:28:40 -07:00
|
|
|
|
2015-05-14 13:38:31 +01:00
|
|
|
if (IS_BROXTON(dev)) {
|
2015-06-18 17:25:54 +03:00
|
|
|
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
|
2015-05-14 13:38:31 +01:00
|
|
|
"pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
|
2015-06-18 17:25:55 +03:00
|
|
|
"pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
|
2015-05-14 13:38:31 +01:00
|
|
|
pipe_config->ddi_pll_sel,
|
|
|
|
|
pipe_config->dpll_hw_state.ebb0,
|
2015-06-18 17:25:54 +03:00
|
|
|
pipe_config->dpll_hw_state.ebb4,
|
2015-05-14 13:38:31 +01:00
|
|
|
pipe_config->dpll_hw_state.pll0,
|
|
|
|
|
pipe_config->dpll_hw_state.pll1,
|
|
|
|
|
pipe_config->dpll_hw_state.pll2,
|
|
|
|
|
pipe_config->dpll_hw_state.pll3,
|
|
|
|
|
pipe_config->dpll_hw_state.pll6,
|
|
|
|
|
pipe_config->dpll_hw_state.pll8,
|
2015-06-18 17:25:54 +03:00
|
|
|
pipe_config->dpll_hw_state.pll9,
|
2015-06-18 17:25:55 +03:00
|
|
|
pipe_config->dpll_hw_state.pll10,
|
2015-05-14 13:38:31 +01:00
|
|
|
pipe_config->dpll_hw_state.pcsdw12);
|
2015-10-28 04:16:45 -07:00
|
|
|
} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
|
2015-05-14 13:38:31 +01:00
|
|
|
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
|
|
|
|
|
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
|
|
|
|
|
pipe_config->ddi_pll_sel,
|
|
|
|
|
pipe_config->dpll_hw_state.ctrl1,
|
|
|
|
|
pipe_config->dpll_hw_state.cfgcr1,
|
|
|
|
|
pipe_config->dpll_hw_state.cfgcr2);
|
|
|
|
|
} else if (HAS_DDI(dev)) {
|
2015-11-16 14:42:12 +01:00
|
|
|
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
|
2015-05-14 13:38:31 +01:00
|
|
|
pipe_config->ddi_pll_sel,
|
2015-11-16 14:42:12 +01:00
|
|
|
pipe_config->dpll_hw_state.wrpll,
|
|
|
|
|
pipe_config->dpll_hw_state.spll);
|
2015-05-14 13:38:31 +01:00
|
|
|
} else {
|
|
|
|
|
DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
|
|
|
|
|
"fp0: 0x%x, fp1: 0x%x\n",
|
|
|
|
|
pipe_config->dpll_hw_state.dpll,
|
|
|
|
|
pipe_config->dpll_hw_state.dpll_md,
|
|
|
|
|
pipe_config->dpll_hw_state.fp0,
|
|
|
|
|
pipe_config->dpll_hw_state.fp1);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-07 15:28:40 -07:00
|
|
|
DRM_DEBUG_KMS("planes on this crtc\n");
|
|
|
|
|
list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
|
|
|
|
|
intel_plane = to_intel_plane(plane);
|
|
|
|
|
if (intel_plane->pipe != crtc->pipe)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
state = to_intel_plane_state(plane->state);
|
|
|
|
|
fb = state->base.fb;
|
|
|
|
|
if (!fb) {
|
|
|
|
|
DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d "
|
|
|
|
|
"disabled, scaler_id = %d\n",
|
|
|
|
|
plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
|
|
|
|
|
plane->base.id, intel_plane->pipe,
|
|
|
|
|
(crtc->base.primary == plane) ? 0 : intel_plane->plane + 1,
|
|
|
|
|
drm_plane_index(plane), state->scaler_id);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d enabled",
|
|
|
|
|
plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
|
|
|
|
|
plane->base.id, intel_plane->pipe,
|
|
|
|
|
crtc->base.primary == plane ? 0 : intel_plane->plane + 1,
|
|
|
|
|
drm_plane_index(plane));
|
|
|
|
|
DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = 0x%x",
|
|
|
|
|
fb->base.id, fb->width, fb->height, fb->pixel_format);
|
|
|
|
|
DRM_DEBUG_KMS("\tscaler:%d src (%u, %u) %ux%u dst (%u, %u) %ux%u\n",
|
|
|
|
|
state->scaler_id,
|
|
|
|
|
state->src.x1 >> 16, state->src.y1 >> 16,
|
|
|
|
|
drm_rect_width(&state->src) >> 16,
|
|
|
|
|
drm_rect_height(&state->src) >> 16,
|
|
|
|
|
state->dst.x1, state->dst.y1,
|
|
|
|
|
drm_rect_width(&state->dst), drm_rect_height(&state->dst));
|
|
|
|
|
}
|
2013-05-28 12:05:54 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-02 14:47:59 +03:00
|
|
|
static bool check_digital_port_conflicts(struct drm_atomic_state *state)
|
2014-12-02 14:10:46 +02:00
|
|
|
{
|
2015-04-02 14:47:59 +03:00
|
|
|
struct drm_device *dev = state->dev;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2014-12-02 14:10:46 +02:00
|
|
|
unsigned int used_ports = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Walk the connector list instead of the encoder
|
|
|
|
|
* list to detect the problem on ddi platforms
|
|
|
|
|
* where there's just one encoder per digital port.
|
|
|
|
|
*/
|
2015-12-10 18:22:31 +02:00
|
|
|
drm_for_each_connector(connector, dev) {
|
|
|
|
|
struct drm_connector_state *connector_state;
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
|
|
|
|
connector_state = drm_atomic_get_existing_connector_state(state, connector);
|
|
|
|
|
if (!connector_state)
|
|
|
|
|
connector_state = connector->state;
|
|
|
|
|
|
2015-04-02 14:47:59 +03:00
|
|
|
if (!connector_state->best_encoder)
|
2014-12-02 14:10:46 +02:00
|
|
|
continue;
|
|
|
|
|
|
2015-04-02 14:47:59 +03:00
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
|
|
|
|
|
WARN_ON(!connector_state->crtc);
|
2014-12-02 14:10:46 +02:00
|
|
|
|
|
|
|
|
switch (encoder->type) {
|
|
|
|
|
unsigned int port_mask;
|
|
|
|
|
case INTEL_OUTPUT_UNKNOWN:
|
|
|
|
|
if (WARN_ON(!HAS_DDI(dev)))
|
|
|
|
|
break;
|
|
|
|
|
case INTEL_OUTPUT_DISPLAYPORT:
|
|
|
|
|
case INTEL_OUTPUT_HDMI:
|
|
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
|
|
port_mask = 1 << enc_to_dig_port(&encoder->base)->port;
|
|
|
|
|
|
|
|
|
|
/* the same port mustn't appear more than once */
|
|
|
|
|
if (used_ports & port_mask)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
used_ports |= port_mask;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
static void
|
|
|
|
|
clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_crtc_state tmp_state;
|
2015-04-07 15:28:41 -07:00
|
|
|
struct intel_crtc_scaler_state scaler_state;
|
2015-04-21 17:13:21 +03:00
|
|
|
struct intel_dpll_hw_state dpll_hw_state;
|
|
|
|
|
enum intel_dpll_id shared_dpll;
|
2015-05-15 11:51:50 +03:00
|
|
|
uint32_t ddi_pll_sel;
|
2015-08-05 12:36:59 +02:00
|
|
|
bool force_thru;
|
2015-03-20 16:18:03 +02:00
|
|
|
|
2015-05-20 09:03:27 +03:00
|
|
|
/* FIXME: before the switch to atomic started, a new pipe_config was
|
|
|
|
|
* kzalloc'd. Code that depends on any field being zero should be
|
|
|
|
|
* fixed, so that the crtc_state can be safely duplicated. For now,
|
|
|
|
|
* only fields that are know to not cause problems are preserved. */
|
|
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
tmp_state = crtc_state->base;
|
2015-04-07 15:28:41 -07:00
|
|
|
scaler_state = crtc_state->scaler_state;
|
2015-04-21 17:13:21 +03:00
|
|
|
shared_dpll = crtc_state->shared_dpll;
|
|
|
|
|
dpll_hw_state = crtc_state->dpll_hw_state;
|
2015-05-15 11:51:50 +03:00
|
|
|
ddi_pll_sel = crtc_state->ddi_pll_sel;
|
2015-08-05 12:36:59 +02:00
|
|
|
force_thru = crtc_state->pch_pfit.force_thru;
|
2015-04-21 17:13:21 +03:00
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
memset(crtc_state, 0, sizeof *crtc_state);
|
2015-04-21 17:13:21 +03:00
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
crtc_state->base = tmp_state;
|
2015-04-07 15:28:41 -07:00
|
|
|
crtc_state->scaler_state = scaler_state;
|
2015-04-21 17:13:21 +03:00
|
|
|
crtc_state->shared_dpll = shared_dpll;
|
|
|
|
|
crtc_state->dpll_hw_state = dpll_hw_state;
|
2015-05-15 11:51:50 +03:00
|
|
|
crtc_state->ddi_pll_sel = ddi_pll_sel;
|
2015-08-05 12:36:59 +02:00
|
|
|
crtc_state->pch_pfit.force_thru = force_thru;
|
2015-03-20 16:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:02 +03:00
|
|
|
static int
|
2013-03-27 00:44:50 +01:00
|
|
|
intel_modeset_pipe_config(struct drm_crtc *crtc,
|
2015-06-15 12:33:38 +02:00
|
|
|
struct intel_crtc_state *pipe_config)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2015-06-15 12:33:38 +02:00
|
|
|
struct drm_atomic_state *state = pipe_config->base.state;
|
2012-07-08 19:40:39 +02:00
|
|
|
struct intel_encoder *encoder;
|
2015-04-21 17:12:59 +03:00
|
|
|
struct drm_connector *connector;
|
2015-03-20 16:18:08 +02:00
|
|
|
struct drm_connector_state *connector_state;
|
2015-04-10 16:22:37 +02:00
|
|
|
int base_bpp, ret = -EINVAL;
|
2015-03-20 16:18:08 +02:00
|
|
|
int i;
|
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 00:00:16 +01:00
|
|
|
bool retry = true;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2015-03-20 16:18:03 +02:00
|
|
|
clear_intel_crtc_state(pipe_config);
|
2012-07-08 19:40:39 +02:00
|
|
|
|
2013-07-04 12:01:15 +02:00
|
|
|
pipe_config->cpu_transcoder =
|
|
|
|
|
(enum transcoder) to_intel_crtc(crtc)->pipe;
|
2013-03-27 00:44:50 +01:00
|
|
|
|
2013-07-30 13:36:32 +03:00
|
|
|
/*
|
|
|
|
|
* Sanitize sync polarity flags based on requested ones. If neither
|
|
|
|
|
* positive or negative polarity is requested, treat this as meaning
|
|
|
|
|
* negative polarity.
|
|
|
|
|
*/
|
2015-01-15 14:55:22 +02:00
|
|
|
if (!(pipe_config->base.adjusted_mode.flags &
|
2013-07-30 13:36:32 +03:00
|
|
|
(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC)))
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC;
|
2013-07-30 13:36:32 +03:00
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
if (!(pipe_config->base.adjusted_mode.flags &
|
2013-07-30 13:36:32 +03:00
|
|
|
(DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)))
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;
|
2013-07-30 13:36:32 +03:00
|
|
|
|
2015-04-10 16:22:37 +02:00
|
|
|
base_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
|
|
|
|
|
pipe_config);
|
|
|
|
|
if (base_bpp < 0)
|
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 00:44:58 +01:00
|
|
|
goto fail;
|
|
|
|
|
|
2013-10-01 22:52:14 +03:00
|
|
|
/*
|
|
|
|
|
* Determine the real pipe dimensions. Note that stereo modes can
|
|
|
|
|
* increase the actual pipe size due to the frame doubling and
|
|
|
|
|
* insertion of additional space for blanks between the frame. This
|
|
|
|
|
* is stored in the crtc timings. We use the requested mode to do this
|
|
|
|
|
* computation to clearly distinguish it from the adjusted mode, which
|
|
|
|
|
* can be changed by the connectors in the below retry loop.
|
|
|
|
|
*/
|
2015-01-15 14:55:22 +02:00
|
|
|
drm_crtc_get_hv_timing(&pipe_config->base.mode,
|
2014-12-01 15:40:09 -08:00
|
|
|
&pipe_config->pipe_src_w,
|
|
|
|
|
&pipe_config->pipe_src_h);
|
2013-10-01 22:52:14 +03: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 00:00:16 +01:00
|
|
|
encoder_retry:
|
2013-06-01 17:17:04 +02:00
|
|
|
/* Ensure the port clock defaults are reset when retrying. */
|
2013-06-01 17:16:21 +02:00
|
|
|
pipe_config->port_clock = 0;
|
2013-06-01 17:17:04 +02:00
|
|
|
pipe_config->pixel_multiplier = 1;
|
2013-06-01 17:16:21 +02:00
|
|
|
|
2013-07-21 21:37:09 +02:00
|
|
|
/* Fill in default crtc timings, allow encoders to overwrite them. */
|
2015-01-15 14:55:22 +02:00
|
|
|
drm_mode_set_crtcinfo(&pipe_config->base.adjusted_mode,
|
|
|
|
|
CRTC_STEREO_DOUBLE);
|
2013-07-21 21:37:09 +02:00
|
|
|
|
2012-07-08 19:40:39 +02: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 15:37:31 +00:00
|
|
|
*/
|
2015-04-21 17:12:59 +03:00
|
|
|
for_each_connector_in_state(state, connector, connector_state, i) {
|
2015-03-20 16:18:08 +02:00
|
|
|
if (connector_state->crtc != crtc)
|
2012-07-08 19:40:39 +02:00
|
|
|
continue;
|
2013-03-27 00:44:52 +01:00
|
|
|
|
2015-03-20 16:18:08 +02:00
|
|
|
encoder = to_intel_encoder(connector_state->best_encoder);
|
|
|
|
|
|
2013-07-21 21:36:59 +02:00
|
|
|
if (!(encoder->compute_config(encoder, pipe_config))) {
|
|
|
|
|
DRM_DEBUG_KMS("Encoder config failure\n");
|
2012-07-08 19:40:39 +02:00
|
|
|
goto fail;
|
|
|
|
|
}
|
2012-04-20 17:11:53 +01:00
|
|
|
}
|
2010-12-03 15:37:31 +00:00
|
|
|
|
2013-06-01 17:16:21 +02:00
|
|
|
/* Set default port clock if not overwritten by the encoder. Needs to be
|
|
|
|
|
* done afterwards in case the encoder adjusts the mode. */
|
|
|
|
|
if (!pipe_config->port_clock)
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->port_clock = pipe_config->base.adjusted_mode.crtc_clock
|
2013-09-25 16:45:37 +01:00
|
|
|
* pipe_config->pixel_multiplier;
|
2013-06-01 17:16:21 +02:00
|
|
|
|
2013-06-07 23:10:32 +02:00
|
|
|
ret = intel_crtc_compute_config(to_intel_crtc(crtc), 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 00:00:16 +01:00
|
|
|
if (ret < 0) {
|
2012-07-08 19:40:39 +02:00
|
|
|
DRM_DEBUG_KMS("CRTC fixup failed\n");
|
|
|
|
|
goto fail;
|
2012-04-20 17:11:53 +01: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 00:00:16 +01: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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-12 11:43:34 +02:00
|
|
|
/* Dithering seems to not pass-through bits correctly when it should, so
|
|
|
|
|
* only enable it on 6bpc panels. */
|
|
|
|
|
pipe_config->dither = pipe_config->pipe_bpp == 6*3;
|
2015-08-26 18:57:26 +02:00
|
|
|
DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
|
2015-04-10 16:22:37 +02:00
|
|
|
base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
|
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 00:44:58 +01:00
|
|
|
|
2012-07-08 19:40:39 +02:00
|
|
|
fail:
|
2015-04-21 17:13:02 +03:00
|
|
|
return ret;
|
2012-04-20 17:11:53 +01:00
|
|
|
}
|
2010-12-03 15:37:31 +00:00
|
|
|
|
2012-07-10 10:42:52 +02:00
|
|
|
static void
|
2015-08-05 12:37:10 +02:00
|
|
|
intel_modeset_update_crtc_state(struct drm_atomic_state *state)
|
2012-07-10 10:42:52 +02:00
|
|
|
{
|
2015-04-21 17:13:04 +03:00
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
2015-07-13 16:30:14 +02:00
|
|
|
int i;
|
2012-07-10 10:42:52 +02:00
|
|
|
|
2014-01-10 11:28:06 +02:00
|
|
|
/* Double check state. */
|
2015-07-13 16:30:14 +02:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
2015-06-01 12:49:49 +02:00
|
|
|
to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
|
2015-06-01 12:50:07 +02:00
|
|
|
|
|
|
|
|
/* Update hwmode for vblank functions */
|
|
|
|
|
if (crtc->state->active)
|
|
|
|
|
crtc->hwmode = crtc->state->adjusted_mode;
|
|
|
|
|
else
|
|
|
|
|
crtc->hwmode.crtc_clock = 0;
|
2015-09-23 16:29:36 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update legacy state to satisfy fbc code. This can
|
|
|
|
|
* be removed when fbc uses the atomic state.
|
|
|
|
|
*/
|
|
|
|
|
if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
|
|
|
|
|
struct drm_plane_state *plane_state = crtc->primary->state;
|
|
|
|
|
|
|
|
|
|
crtc->primary->fb = plane_state->fb;
|
|
|
|
|
crtc->x = plane_state->src_x >> 16;
|
|
|
|
|
crtc->y = plane_state->src_y >> 16;
|
|
|
|
|
}
|
2012-07-10 10:42:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-06 23:29:02 +03:00
|
|
|
static bool intel_fuzzy_clock_check(int clock1, int clock2)
|
2013-06-27 00:39:25 +03:00
|
|
|
{
|
2013-09-06 23:29:02 +03:00
|
|
|
int diff;
|
2013-06-27 00:39:25 +03:00
|
|
|
|
|
|
|
|
if (clock1 == clock2)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (!clock1 || !clock2)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
diff = abs(clock1 - clock2);
|
|
|
|
|
|
|
|
|
|
if (((((diff + clock1 + clock2) * 100)) / (clock1 + clock2)) < 105)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-08 22:08:04 +02:00
|
|
|
#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
|
|
|
|
|
list_for_each_entry((intel_crtc), \
|
|
|
|
|
&(dev)->mode_config.crtc_list, \
|
|
|
|
|
base.head) \
|
2015-11-24 21:21:56 +02:00
|
|
|
for_each_if (mask & (1 <<(intel_crtc)->pipe))
|
2012-07-08 22:08:04 +02:00
|
|
|
|
2015-07-14 12:17:40 +02:00
|
|
|
static bool
|
|
|
|
|
intel_compare_m_n(unsigned int m, unsigned int n,
|
|
|
|
|
unsigned int m2, unsigned int n2,
|
|
|
|
|
bool exact)
|
|
|
|
|
{
|
|
|
|
|
if (m == m2 && n == n2)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (exact || !m || !n || !m2 || !n2)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
|
|
|
|
|
|
2016-01-06 13:54:43 +01:00
|
|
|
if (n > n2) {
|
|
|
|
|
while (n > n2) {
|
2015-07-14 12:17:40 +02:00
|
|
|
m2 <<= 1;
|
|
|
|
|
n2 <<= 1;
|
|
|
|
|
}
|
2016-01-06 13:54:43 +01:00
|
|
|
} else if (n < n2) {
|
|
|
|
|
while (n < n2) {
|
2015-07-14 12:17:40 +02:00
|
|
|
m <<= 1;
|
|
|
|
|
n <<= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-06 13:54:43 +01:00
|
|
|
if (n != n2)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return intel_fuzzy_clock_check(m, m2);
|
2015-07-14 12:17:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
intel_compare_link_m_n(const struct intel_link_m_n *m_n,
|
|
|
|
|
struct intel_link_m_n *m2_n2,
|
|
|
|
|
bool adjust)
|
|
|
|
|
{
|
|
|
|
|
if (m_n->tu == m2_n2->tu &&
|
|
|
|
|
intel_compare_m_n(m_n->gmch_m, m_n->gmch_n,
|
|
|
|
|
m2_n2->gmch_m, m2_n2->gmch_n, !adjust) &&
|
|
|
|
|
intel_compare_m_n(m_n->link_m, m_n->link_n,
|
|
|
|
|
m2_n2->link_m, m2_n2->link_n, !adjust)) {
|
|
|
|
|
if (adjust)
|
|
|
|
|
*m2_n2 = *m_n;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-28 10:42:00 +01:00
|
|
|
static bool
|
2013-05-07 23:34:16 +02:00
|
|
|
intel_pipe_config_compare(struct drm_device *dev,
|
2015-01-15 14:55:21 +02:00
|
|
|
struct intel_crtc_state *current_config,
|
2015-07-14 12:17:40 +02:00
|
|
|
struct intel_crtc_state *pipe_config,
|
|
|
|
|
bool adjust)
|
2013-03-28 10:42:00 +01:00
|
|
|
{
|
2015-07-14 12:17:40 +02:00
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
|
|
#define INTEL_ERR_OR_DBG_KMS(fmt, ...) \
|
|
|
|
|
do { \
|
|
|
|
|
if (!adjust) \
|
|
|
|
|
DRM_ERROR(fmt, ##__VA_ARGS__); \
|
|
|
|
|
else \
|
|
|
|
|
DRM_DEBUG_KMS(fmt, ##__VA_ARGS__); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2013-06-05 13:34:20 +02:00
|
|
|
#define PIPE_CONF_CHECK_X(name) \
|
|
|
|
|
if (current_config->name != pipe_config->name) { \
|
2015-07-14 12:17:40 +02:00
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
2013-06-05 13:34:20 +02:00
|
|
|
"(expected 0x%08x, found 0x%08x)\n", \
|
|
|
|
|
current_config->name, \
|
|
|
|
|
pipe_config->name); \
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = false; \
|
2013-06-05 13:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-19 11:25:34 +02:00
|
|
|
#define PIPE_CONF_CHECK_I(name) \
|
|
|
|
|
if (current_config->name != pipe_config->name) { \
|
2015-07-14 12:17:40 +02:00
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
2013-04-19 11:25:34 +02:00
|
|
|
"(expected %i, found %i)\n", \
|
|
|
|
|
current_config->name, \
|
|
|
|
|
pipe_config->name); \
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = false; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define PIPE_CONF_CHECK_M_N(name) \
|
|
|
|
|
if (!intel_compare_link_m_n(¤t_config->name, \
|
|
|
|
|
&pipe_config->name,\
|
|
|
|
|
adjust)) { \
|
|
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
|
|
|
|
"(expected tu %i gmch %i/%i link %i/%i, " \
|
|
|
|
|
"found tu %i, gmch %i/%i link %i/%i)\n", \
|
|
|
|
|
current_config->name.tu, \
|
|
|
|
|
current_config->name.gmch_m, \
|
|
|
|
|
current_config->name.gmch_n, \
|
|
|
|
|
current_config->name.link_m, \
|
|
|
|
|
current_config->name.link_n, \
|
|
|
|
|
pipe_config->name.tu, \
|
|
|
|
|
pipe_config->name.gmch_m, \
|
|
|
|
|
pipe_config->name.gmch_n, \
|
|
|
|
|
pipe_config->name.link_m, \
|
|
|
|
|
pipe_config->name.link_n); \
|
|
|
|
|
ret = false; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \
|
|
|
|
|
if (!intel_compare_link_m_n(¤t_config->name, \
|
|
|
|
|
&pipe_config->name, adjust) && \
|
|
|
|
|
!intel_compare_link_m_n(¤t_config->alt_name, \
|
|
|
|
|
&pipe_config->name, adjust)) { \
|
|
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
|
|
|
|
"(expected tu %i gmch %i/%i link %i/%i, " \
|
|
|
|
|
"or tu %i gmch %i/%i link %i/%i, " \
|
|
|
|
|
"found tu %i, gmch %i/%i link %i/%i)\n", \
|
|
|
|
|
current_config->name.tu, \
|
|
|
|
|
current_config->name.gmch_m, \
|
|
|
|
|
current_config->name.gmch_n, \
|
|
|
|
|
current_config->name.link_m, \
|
|
|
|
|
current_config->name.link_n, \
|
|
|
|
|
current_config->alt_name.tu, \
|
|
|
|
|
current_config->alt_name.gmch_m, \
|
|
|
|
|
current_config->alt_name.gmch_n, \
|
|
|
|
|
current_config->alt_name.link_m, \
|
|
|
|
|
current_config->alt_name.link_n, \
|
|
|
|
|
pipe_config->name.tu, \
|
|
|
|
|
pipe_config->name.gmch_m, \
|
|
|
|
|
pipe_config->name.gmch_n, \
|
|
|
|
|
pipe_config->name.link_m, \
|
|
|
|
|
pipe_config->name.link_n); \
|
|
|
|
|
ret = false; \
|
2013-03-28 10:42:01 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-05 07:51:23 -07:00
|
|
|
/* This is required for BDW+ where there is only one set of registers for
|
|
|
|
|
* switching between high and low RR.
|
|
|
|
|
* This macro can be used whenever a comparison has to be made between one
|
|
|
|
|
* hw state and multiple sw state variables.
|
|
|
|
|
*/
|
|
|
|
|
#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
|
|
|
|
|
if ((current_config->name != pipe_config->name) && \
|
|
|
|
|
(current_config->alt_name != pipe_config->name)) { \
|
2015-07-14 12:17:40 +02:00
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
2014-08-05 07:51:23 -07:00
|
|
|
"(expected %i or %i, found %i)\n", \
|
|
|
|
|
current_config->name, \
|
|
|
|
|
current_config->alt_name, \
|
|
|
|
|
pipe_config->name); \
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = false; \
|
2014-08-05 07:51:23 -07:00
|
|
|
}
|
|
|
|
|
|
2013-04-29 21:56:12 +02:00
|
|
|
#define PIPE_CONF_CHECK_FLAGS(name, mask) \
|
|
|
|
|
if ((current_config->name ^ pipe_config->name) & (mask)) { \
|
2015-07-14 12:17:40 +02:00
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") " \
|
2013-04-29 21:56:12 +02:00
|
|
|
"(expected %i, found %i)\n", \
|
|
|
|
|
current_config->name & (mask), \
|
|
|
|
|
pipe_config->name & (mask)); \
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = false; \
|
2013-04-29 21:56:12 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-06 23:29:07 +03:00
|
|
|
#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \
|
|
|
|
|
if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \
|
2015-07-14 12:17:40 +02:00
|
|
|
INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
|
2013-09-06 23:29:07 +03:00
|
|
|
"(expected %i, found %i)\n", \
|
|
|
|
|
current_config->name, \
|
|
|
|
|
pipe_config->name); \
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = false; \
|
2013-09-06 23:29:07 +03:00
|
|
|
}
|
|
|
|
|
|
2013-06-06 14:55:52 +02:00
|
|
|
#define PIPE_CONF_QUIRK(quirk) \
|
|
|
|
|
((current_config->quirks | pipe_config->quirks) & (quirk))
|
|
|
|
|
|
2013-05-22 00:50:22 +02:00
|
|
|
PIPE_CONF_CHECK_I(cpu_transcoder);
|
|
|
|
|
|
2013-04-19 11:25:34 +02:00
|
|
|
PIPE_CONF_CHECK_I(has_pch_encoder);
|
|
|
|
|
PIPE_CONF_CHECK_I(fdi_lanes);
|
2015-07-14 12:17:40 +02:00
|
|
|
PIPE_CONF_CHECK_M_N(fdi_m_n);
|
2013-04-19 11:25:34 +02:00
|
|
|
|
2013-09-10 17:02:54 +03:00
|
|
|
PIPE_CONF_CHECK_I(has_dp_encoder);
|
2015-07-06 16:39:15 +03:00
|
|
|
PIPE_CONF_CHECK_I(lane_count);
|
2014-08-05 07:51:23 -07:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 8) {
|
2015-07-14 12:17:40 +02:00
|
|
|
PIPE_CONF_CHECK_M_N(dp_m_n);
|
|
|
|
|
|
|
|
|
|
if (current_config->has_drrs)
|
|
|
|
|
PIPE_CONF_CHECK_M_N(dp_m2_n2);
|
|
|
|
|
} else
|
|
|
|
|
PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
|
2013-09-10 17:02:54 +03:00
|
|
|
|
2015-11-27 12:21:46 +02:00
|
|
|
PIPE_CONF_CHECK_I(has_dsi_encoder);
|
|
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_end);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_start);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_end);
|
2013-04-29 21:56:12 +02:00
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vdisplay);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vtotal);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_start);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_end);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_start);
|
|
|
|
|
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end);
|
2013-04-29 21:56:12 +02:00
|
|
|
|
2013-06-27 19:47:19 +02:00
|
|
|
PIPE_CONF_CHECK_I(pixel_multiplier);
|
2014-04-24 23:54:47 +02:00
|
|
|
PIPE_CONF_CHECK_I(has_hdmi_sink);
|
2014-04-24 23:54:49 +02:00
|
|
|
if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
|
2015-12-09 12:29:35 -08:00
|
|
|
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
2014-04-24 23:54:49 +02:00
|
|
|
PIPE_CONF_CHECK_I(limited_color_range);
|
2014-11-05 14:26:08 -08:00
|
|
|
PIPE_CONF_CHECK_I(has_infoframe);
|
2013-06-06 12:45:25 +02:00
|
|
|
|
2014-04-24 23:54:52 +02:00
|
|
|
PIPE_CONF_CHECK_I(has_audio);
|
|
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
|
2013-04-29 21:56:12 +02:00
|
|
|
DRM_MODE_FLAG_INTERLACE);
|
|
|
|
|
|
2013-06-06 14:55:52 +02:00
|
|
|
if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) {
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
|
2013-06-06 14:55:52 +02:00
|
|
|
DRM_MODE_FLAG_PHSYNC);
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
|
2013-06-06 14:55:52 +02:00
|
|
|
DRM_MODE_FLAG_NHSYNC);
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
|
2013-06-06 14:55:52 +02:00
|
|
|
DRM_MODE_FLAG_PVSYNC);
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
|
2013-06-06 14:55:52 +02:00
|
|
|
DRM_MODE_FLAG_NVSYNC);
|
|
|
|
|
}
|
2013-05-14 17:08:26 -07:00
|
|
|
|
2015-09-03 21:50:16 +03:00
|
|
|
PIPE_CONF_CHECK_X(gmch_pfit.control);
|
2015-07-15 14:15:50 +02:00
|
|
|
/* pfit ratios are autocomputed by the hw on gen4+ */
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 4)
|
|
|
|
|
PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
|
2015-09-03 21:50:16 +03:00
|
|
|
PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
|
2014-04-13 12:00:33 +02:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
if (!adjust) {
|
|
|
|
|
PIPE_CONF_CHECK_I(pipe_src_w);
|
|
|
|
|
PIPE_CONF_CHECK_I(pipe_src_h);
|
|
|
|
|
|
|
|
|
|
PIPE_CONF_CHECK_I(pch_pfit.enabled);
|
|
|
|
|
if (current_config->pch_pfit.enabled) {
|
|
|
|
|
PIPE_CONF_CHECK_X(pch_pfit.pos);
|
|
|
|
|
PIPE_CONF_CHECK_X(pch_pfit.size);
|
|
|
|
|
}
|
2013-05-07 23:34:16 +02:00
|
|
|
|
2015-09-14 11:30:10 +02:00
|
|
|
PIPE_CONF_CHECK_I(scaler_state.scaler_id);
|
|
|
|
|
}
|
2015-04-07 15:28:45 -07:00
|
|
|
|
2014-01-07 13:30:45 -08:00
|
|
|
/* BDW+ don't expose a synchronous way to read the state */
|
|
|
|
|
if (IS_HASWELL(dev))
|
|
|
|
|
PIPE_CONF_CHECK_I(ips_enabled);
|
2013-05-31 16:33:22 -03:00
|
|
|
|
2013-09-04 18:30:03 +03:00
|
|
|
PIPE_CONF_CHECK_I(double_wide);
|
|
|
|
|
|
2014-06-25 22:01:55 +03:00
|
|
|
PIPE_CONF_CHECK_X(ddi_pll_sel);
|
|
|
|
|
|
2013-06-07 23:11:08 +02:00
|
|
|
PIPE_CONF_CHECK_I(shared_dpll);
|
2013-06-05 13:34:20 +02:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
|
2013-06-05 13:34:28 +02:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
|
2013-06-05 13:34:20 +02:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
|
|
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
|
2014-07-04 11:27:39 -03:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
|
2015-11-16 14:42:12 +01:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.spll);
|
2014-11-13 14:55:21 +00:00
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
|
|
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
|
|
|
|
|
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
|
2013-06-07 23:11:08 +02:00
|
|
|
|
2013-09-06 23:29:00 +03:00
|
|
|
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
|
|
|
|
|
PIPE_CONF_CHECK_I(pipe_bpp);
|
|
|
|
|
|
2015-01-15 14:55:22 +02:00
|
|
|
PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock);
|
2014-01-20 14:18:04 -08:00
|
|
|
PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
|
2013-09-06 23:29:07 +03:00
|
|
|
|
2013-06-05 13:34:20 +02:00
|
|
|
#undef PIPE_CONF_CHECK_X
|
2013-04-19 11:25:34 +02:00
|
|
|
#undef PIPE_CONF_CHECK_I
|
2014-08-05 07:51:23 -07:00
|
|
|
#undef PIPE_CONF_CHECK_I_ALT
|
2013-04-29 21:56:12 +02:00
|
|
|
#undef PIPE_CONF_CHECK_FLAGS
|
2013-09-06 23:29:07 +03:00
|
|
|
#undef PIPE_CONF_CHECK_CLOCK_FUZZY
|
2013-06-06 14:55:52 +02:00
|
|
|
#undef PIPE_CONF_QUIRK
|
2015-07-14 12:17:40 +02:00
|
|
|
#undef INTEL_ERR_OR_DBG_KMS
|
2013-03-28 10:42:01 +01:00
|
|
|
|
2015-07-14 12:17:40 +02:00
|
|
|
return ret;
|
2013-03-28 10:42:00 +01:00
|
|
|
}
|
|
|
|
|
|
2014-11-04 17:06:52 +00:00
|
|
|
static void check_wm_state(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct skl_ddb_allocation hw_ddb, *sw_ddb;
|
|
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
|
int plane;
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 9)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
skl_ddb_get_hw_state(dev_priv, &hw_ddb);
|
|
|
|
|
sw_ddb = &dev_priv->wm.skl_hw.ddb;
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(dev, intel_crtc) {
|
|
|
|
|
struct skl_ddb_entry *hw_entry, *sw_entry;
|
|
|
|
|
const enum pipe pipe = intel_crtc->pipe;
|
|
|
|
|
|
|
|
|
|
if (!intel_crtc->active)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* planes */
|
2015-02-28 14:54:08 +00:00
|
|
|
for_each_plane(dev_priv, pipe, plane) {
|
2014-11-04 17:06:52 +00:00
|
|
|
hw_entry = &hw_ddb.plane[pipe][plane];
|
|
|
|
|
sw_entry = &sw_ddb->plane[pipe][plane];
|
|
|
|
|
|
|
|
|
|
if (skl_ddb_entry_equal(hw_entry, sw_entry))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
DRM_ERROR("mismatch in DDB state pipe %c plane %d "
|
|
|
|
|
"(expected (%u,%u), found (%u,%u))\n",
|
|
|
|
|
pipe_name(pipe), plane + 1,
|
|
|
|
|
sw_entry->start, sw_entry->end,
|
|
|
|
|
hw_entry->start, hw_entry->end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* cursor */
|
2015-09-24 15:53:10 -07:00
|
|
|
hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
|
|
|
|
|
sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
|
2014-11-04 17:06:52 +00:00
|
|
|
|
|
|
|
|
if (skl_ddb_entry_equal(hw_entry, sw_entry))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
DRM_ERROR("mismatch in DDB state pipe %c cursor "
|
|
|
|
|
"(expected (%u,%u), found (%u,%u))\n",
|
|
|
|
|
pipe_name(pipe),
|
|
|
|
|
sw_entry->start, sw_entry->end,
|
|
|
|
|
hw_entry->start, hw_entry->end);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:18 +02:00
|
|
|
static void
|
2015-08-06 13:49:22 +02:00
|
|
|
check_connector_state(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *old_state)
|
2012-07-10 09:50:11 +02:00
|
|
|
{
|
2015-08-06 13:49:22 +02:00
|
|
|
struct drm_connector_state *old_conn_state;
|
|
|
|
|
struct drm_connector *connector;
|
|
|
|
|
int i;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-08-06 13:49:22 +02:00
|
|
|
for_each_connector_in_state(old_state, connector, old_conn_state, i) {
|
|
|
|
|
struct drm_encoder *encoder = connector->encoder;
|
|
|
|
|
struct drm_connector_state *state = connector->state;
|
2015-07-13 16:30:26 +02:00
|
|
|
|
2012-07-10 09:50:11 +02:00
|
|
|
/* This also checks the encoder/connector hw state with the
|
|
|
|
|
* ->get_hw_state callbacks. */
|
2015-08-06 13:49:22 +02:00
|
|
|
intel_connector_check_state(to_intel_connector(connector));
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-07-13 16:30:26 +02:00
|
|
|
I915_STATE_WARN(state->best_encoder != encoder,
|
2015-08-06 13:49:22 +02:00
|
|
|
"connector's atomic encoder doesn't match legacy encoder\n");
|
2012-07-10 09:50:11 +02:00
|
|
|
}
|
2013-06-05 13:34:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_encoder_state(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
struct intel_connector *connector;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
2012-07-10 09:50:11 +02:00
|
|
|
bool enabled = false;
|
2015-08-05 12:37:05 +02:00
|
|
|
enum pipe pipe;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
|
|
|
|
|
encoder->base.base.id,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.name);
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-03-03 15:21:56 +02:00
|
|
|
for_each_intel_connector(dev, connector) {
|
2015-08-05 12:37:05 +02:00
|
|
|
if (connector->base.state->best_encoder != &encoder->base)
|
2012-07-10 09:50:11 +02:00
|
|
|
continue;
|
|
|
|
|
enabled = true;
|
2015-07-13 16:30:26 +02:00
|
|
|
|
|
|
|
|
I915_STATE_WARN(connector->base.state->crtc !=
|
|
|
|
|
encoder->base.crtc,
|
|
|
|
|
"connector's crtc doesn't match encoder crtc\n");
|
2012-07-10 09:50:11 +02:00
|
|
|
}
|
2014-05-02 14:02:48 +10:00
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(!!encoder->base.crtc != enabled,
|
2012-07-10 09:50:11 +02:00
|
|
|
"encoder's enabled state mismatch "
|
|
|
|
|
"(expected %i, found %i)\n",
|
|
|
|
|
!!encoder->base.crtc, enabled);
|
2015-08-05 12:37:04 +02:00
|
|
|
|
|
|
|
|
if (!encoder->base.crtc) {
|
2015-08-05 12:37:05 +02:00
|
|
|
bool active;
|
2015-08-05 12:37:04 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
active = encoder->get_hw_state(encoder, &pipe);
|
|
|
|
|
I915_STATE_WARN(active,
|
|
|
|
|
"encoder detached but still enabled on pipe %c.\n",
|
|
|
|
|
pipe_name(pipe));
|
2015-08-05 12:37:04 +02:00
|
|
|
}
|
2012-07-10 09:50:11 +02:00
|
|
|
}
|
2013-06-05 13:34:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-08-05 12:37:05 +02:00
|
|
|
check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state)
|
2013-06-05 13:34:18 +02:00
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-05 13:34:18 +02:00
|
|
|
struct intel_encoder *encoder;
|
2015-08-05 12:37:05 +02:00
|
|
|
struct drm_crtc_state *old_crtc_state;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
int i;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
struct intel_crtc_state *pipe_config, *sw_config;
|
2015-08-05 12:37:03 +02:00
|
|
|
bool active;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
if (!needs_modeset(crtc->state) &&
|
|
|
|
|
!to_intel_crtc_state(crtc->state)->update_pipe)
|
2015-08-05 12:37:05 +02:00
|
|
|
continue;
|
2013-05-14 17:08:26 -07:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
__drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state);
|
|
|
|
|
pipe_config = to_intel_crtc_state(old_crtc_state);
|
|
|
|
|
memset(pipe_config, 0, sizeof(*pipe_config));
|
|
|
|
|
pipe_config->base.crtc = crtc;
|
|
|
|
|
pipe_config->base.state = old_state;
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
DRM_DEBUG_KMS("[CRTC:%d]\n",
|
|
|
|
|
crtc->base.id);
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
active = dev_priv->display.get_pipe_config(intel_crtc,
|
|
|
|
|
pipe_config);
|
2013-05-29 10:41:29 +02:00
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
/* hw state is inconsistent with the pipe quirk */
|
2015-08-05 12:37:05 +02:00
|
|
|
if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
|
|
|
|
|
(intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
|
|
|
|
|
active = crtc->state->active;
|
2013-06-06 12:45:25 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
I915_STATE_WARN(crtc->state->active != active,
|
2013-03-28 10:42:00 +01:00
|
|
|
"crtc active state doesn't match with hw state "
|
2015-08-05 12:37:05 +02:00
|
|
|
"(expected %i, found %i)\n", crtc->state->active, active);
|
2013-03-28 10:42:00 +01:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
I915_STATE_WARN(intel_crtc->active != crtc->state->active,
|
2015-06-01 12:49:52 +02:00
|
|
|
"transitional active state does not match atomic hw state "
|
2015-08-05 12:37:05 +02:00
|
|
|
"(expected %i, found %i)\n", crtc->state->active, intel_crtc->active);
|
|
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
|
|
enum pipe pipe;
|
|
|
|
|
|
|
|
|
|
active = encoder->get_hw_state(encoder, &pipe);
|
|
|
|
|
I915_STATE_WARN(active != crtc->state->active,
|
|
|
|
|
"[ENCODER:%i] active %i with crtc active %i\n",
|
|
|
|
|
encoder->base.base.id, active, crtc->state->active);
|
|
|
|
|
|
|
|
|
|
I915_STATE_WARN(active && intel_crtc->pipe != pipe,
|
|
|
|
|
"Encoder connected to wrong pipe %c\n",
|
|
|
|
|
pipe_name(pipe));
|
|
|
|
|
|
|
|
|
|
if (active)
|
|
|
|
|
encoder->get_config(encoder, pipe_config);
|
|
|
|
|
}
|
2015-06-01 12:49:52 +02:00
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
if (!crtc->state->active)
|
2015-07-14 12:17:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
2015-08-05 12:37:05 +02:00
|
|
|
sw_config = to_intel_crtc_state(crtc->state);
|
|
|
|
|
if (!intel_pipe_config_compare(dev, sw_config,
|
|
|
|
|
pipe_config, false)) {
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(1, "pipe state doesn't match!\n");
|
2015-08-05 12:37:05 +02:00
|
|
|
intel_dump_pipe_config(intel_crtc, pipe_config,
|
2013-05-28 12:05:54 +02:00
|
|
|
"[hw state]");
|
2015-08-05 12:37:05 +02:00
|
|
|
intel_dump_pipe_config(intel_crtc, sw_config,
|
2013-05-28 12:05:54 +02:00
|
|
|
"[sw state]");
|
|
|
|
|
}
|
2012-07-10 09:50:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:18 +02:00
|
|
|
static void
|
|
|
|
|
check_shared_dpll_state(struct drm_device *dev)
|
|
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-05 13:34:18 +02:00
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
struct intel_dpll_hw_state dpll_hw_state;
|
|
|
|
|
int i;
|
2013-06-05 13:34:16 +02:00
|
|
|
|
|
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
|
|
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
|
|
|
|
int enabled_crtcs = 0, active_crtcs = 0;
|
|
|
|
|
bool active;
|
|
|
|
|
|
|
|
|
|
memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("%s\n", pll->name);
|
|
|
|
|
|
|
|
|
|
active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
|
|
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask),
|
2013-06-05 13:34:16 +02:00
|
|
|
"more active pll users than references: %i vs %i\n",
|
2014-10-29 11:32:32 +02:00
|
|
|
pll->active, hweight32(pll->config.crtc_mask));
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->active && !pll->on,
|
2013-06-05 13:34:16 +02:00
|
|
|
"pll in active use but not on in sw tracking\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->on && !pll->active,
|
2013-07-17 06:55:04 +02:00
|
|
|
"pll in on but not on in use in sw tracking\n");
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->on != active,
|
2013-06-05 13:34:16 +02:00
|
|
|
"pll on state mismatch (expected %i, found %i)\n",
|
|
|
|
|
pll->on, active);
|
|
|
|
|
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2015-02-25 13:12:16 -08:00
|
|
|
if (crtc->base.state->enable && intel_crtc_to_shared_dpll(crtc) == pll)
|
2013-06-05 13:34:16 +02:00
|
|
|
enabled_crtcs++;
|
|
|
|
|
if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
|
|
|
|
|
active_crtcs++;
|
|
|
|
|
}
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->active != active_crtcs,
|
2013-06-05 13:34:16 +02:00
|
|
|
"pll active crtcs mismatch (expected %i, found %i)\n",
|
|
|
|
|
pll->active, active_crtcs);
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs,
|
2013-06-05 13:34:16 +02:00
|
|
|
"pll enabled crtcs mismatch (expected %i, found %i)\n",
|
2014-10-29 11:32:32 +02:00
|
|
|
hweight32(pll->config.crtc_mask), enabled_crtcs);
|
2013-06-05 13:34:20 +02:00
|
|
|
|
2014-12-15 13:56:32 -05:00
|
|
|
I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state,
|
2013-06-05 13:34:20 +02:00
|
|
|
sizeof(dpll_hw_state)),
|
|
|
|
|
"pll hw state mismatch\n");
|
2013-06-05 13:34:16 +02:00
|
|
|
}
|
2012-07-10 09:50:11 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-05 12:37:00 +02:00
|
|
|
static void
|
|
|
|
|
intel_modeset_check_state(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *old_state)
|
2013-06-05 13:34:18 +02:00
|
|
|
{
|
2014-11-04 17:06:52 +00:00
|
|
|
check_wm_state(dev);
|
2015-08-06 13:49:22 +02:00
|
|
|
check_connector_state(dev, old_state);
|
2013-06-05 13:34:18 +02:00
|
|
|
check_encoder_state(dev);
|
2015-08-05 12:37:05 +02:00
|
|
|
check_crtc_state(dev, old_state);
|
2013-06-05 13:34:18 +02:00
|
|
|
check_shared_dpll_state(dev);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 14:55:21 +02:00
|
|
|
void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
|
2013-09-13 16:00:08 +03:00
|
|
|
int dotclock)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* FDI already provided one idea for the dotclock.
|
|
|
|
|
* Yell if the encoder disagrees.
|
|
|
|
|
*/
|
2015-01-15 14:55:22 +02:00
|
|
|
WARN(!intel_fuzzy_clock_check(pipe_config->base.adjusted_mode.crtc_clock, dotclock),
|
2013-09-13 16:00:08 +03:00
|
|
|
"FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
|
2015-01-15 14:55:22 +02:00
|
|
|
pipe_config->base.adjusted_mode.crtc_clock, dotclock);
|
2013-09-13 16:00:08 +03:00
|
|
|
}
|
|
|
|
|
|
2014-05-15 20:23:23 +03:00
|
|
|
static void update_scanline_offset(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The scanline counter increments at the leading edge of hsync.
|
|
|
|
|
*
|
|
|
|
|
* On most platforms it starts counting from vtotal-1 on the
|
|
|
|
|
* first active line. That means the scanline counter value is
|
|
|
|
|
* always one less than what we would expect. Ie. just after
|
|
|
|
|
* start of vblank, which also occurs at start of hsync (on the
|
|
|
|
|
* last active line), the scanline counter will read vblank_start-1.
|
|
|
|
|
*
|
|
|
|
|
* On gen2 the scanline counter starts counting from 1 instead
|
|
|
|
|
* of vtotal-1, so we have to subtract one (or rather add vtotal-1
|
|
|
|
|
* to keep the value positive), instead of adding one.
|
|
|
|
|
*
|
|
|
|
|
* On HSW+ the behaviour of the scanline counter depends on the output
|
|
|
|
|
* type. For DP ports it behaves like most other platforms, but on HDMI
|
|
|
|
|
* there's an extra 1 line difference. So we need to add two instead of
|
|
|
|
|
* one to the value.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_GEN2(dev)) {
|
2015-09-08 13:40:45 +03:00
|
|
|
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
2014-05-15 20:23:23 +03:00
|
|
|
int vtotal;
|
|
|
|
|
|
2015-09-08 13:40:45 +03:00
|
|
|
vtotal = adjusted_mode->crtc_vtotal;
|
|
|
|
|
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
2014-05-15 20:23:23 +03:00
|
|
|
vtotal /= 2;
|
|
|
|
|
|
|
|
|
|
crtc->scanline_offset = vtotal - 1;
|
|
|
|
|
} else if (HAS_DDI(dev) &&
|
2014-10-20 13:46:45 +03:00
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
|
2014-05-15 20:23:23 +03:00
|
|
|
crtc->scanline_offset = 2;
|
|
|
|
|
} else
|
|
|
|
|
crtc->scanline_offset = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
static void intel_modeset_clear_plls(struct drm_atomic_state *state)
|
2015-01-29 16:55:08 +02:00
|
|
|
{
|
2015-04-02 14:47:57 +03:00
|
|
|
struct drm_device *dev = state->dev;
|
2015-01-29 16:55:08 +02:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
2015-06-15 12:33:42 +02:00
|
|
|
struct intel_shared_dpll_config *shared_dpll = NULL;
|
2015-01-29 16:55:08 +02:00
|
|
|
struct intel_crtc *intel_crtc;
|
2015-04-21 17:13:04 +03:00
|
|
|
struct intel_crtc_state *intel_crtc_state;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
int i;
|
2015-01-29 16:55:08 +02:00
|
|
|
|
|
|
|
|
if (!dev_priv->display.crtc_compute_clock)
|
2015-06-15 12:33:42 +02:00
|
|
|
return;
|
2015-01-29 16:55:08 +02:00
|
|
|
|
2015-04-21 17:13:04 +03:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
2015-06-15 12:33:42 +02:00
|
|
|
int dpll;
|
|
|
|
|
|
2015-04-21 17:13:04 +03:00
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
2015-04-21 17:13:21 +03:00
|
|
|
intel_crtc_state = to_intel_crtc_state(crtc_state);
|
2015-06-15 12:33:42 +02:00
|
|
|
dpll = intel_crtc_state->shared_dpll;
|
2015-04-21 17:13:04 +03:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
if (!needs_modeset(crtc_state) || dpll == DPLL_ID_PRIVATE)
|
2015-04-02 14:47:57 +03:00
|
|
|
continue;
|
|
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
intel_crtc_state->shared_dpll = DPLL_ID_PRIVATE;
|
2015-04-21 17:13:04 +03:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
if (!shared_dpll)
|
|
|
|
|
shared_dpll = intel_atomic_get_shared_dpll_state(state);
|
2015-01-29 16:55:08 +02:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
shared_dpll[dpll].crtc_mask &= ~(1 << intel_crtc->pipe);
|
|
|
|
|
}
|
2015-01-29 16:55:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-01 12:50:09 +02:00
|
|
|
/*
|
|
|
|
|
* This implements the workaround described in the "notes" section of the mode
|
|
|
|
|
* set sequence documentation. When going from no pipes or single pipe to
|
|
|
|
|
* multiple pipes, and planes are enabled after the pipe, we need to wait at
|
|
|
|
|
* least 2 vblanks on the first pipe before enabling planes on the second pipe.
|
|
|
|
|
*/
|
|
|
|
|
static int haswell_mode_set_planes_workaround(struct drm_atomic_state *state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct intel_crtc_state *first_crtc_state = NULL;
|
|
|
|
|
struct intel_crtc_state *other_crtc_state = NULL;
|
|
|
|
|
enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* look at all crtc's that are going to be enabled in during modeset */
|
|
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
|
|
if (!crtc_state->active || !needs_modeset(crtc_state))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (first_crtc_state) {
|
|
|
|
|
other_crtc_state = to_intel_crtc_state(crtc_state);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
first_crtc_state = to_intel_crtc_state(crtc_state);
|
|
|
|
|
first_pipe = intel_crtc->pipe;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No workaround needed? */
|
|
|
|
|
if (!first_crtc_state)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* w/a possibly needed, check how many crtc's are already enabled. */
|
|
|
|
|
for_each_intel_crtc(state->dev, intel_crtc) {
|
|
|
|
|
struct intel_crtc_state *pipe_config;
|
|
|
|
|
|
|
|
|
|
pipe_config = intel_atomic_get_crtc_state(state, intel_crtc);
|
|
|
|
|
if (IS_ERR(pipe_config))
|
|
|
|
|
return PTR_ERR(pipe_config);
|
|
|
|
|
|
|
|
|
|
pipe_config->hsw_workaround_pipe = INVALID_PIPE;
|
|
|
|
|
|
|
|
|
|
if (!pipe_config->base.active ||
|
|
|
|
|
needs_modeset(&pipe_config->base))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* 2 or more enabled crtcs means no need for w/a */
|
|
|
|
|
if (enabled_pipe != INVALID_PIPE)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
enabled_pipe = intel_crtc->pipe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (enabled_pipe != INVALID_PIPE)
|
|
|
|
|
first_crtc_state->hsw_workaround_pipe = enabled_pipe;
|
|
|
|
|
else if (other_crtc_state)
|
|
|
|
|
other_crtc_state->hsw_workaround_pipe = first_pipe;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:56 +02:00
|
|
|
static int intel_modeset_all_pipes(struct drm_atomic_state *state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
/* add all active pipes to the state */
|
|
|
|
|
for_each_crtc(state->dev, crtc) {
|
|
|
|
|
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
|
|
|
if (IS_ERR(crtc_state))
|
|
|
|
|
return PTR_ERR(crtc_state);
|
|
|
|
|
|
|
|
|
|
if (!crtc_state->active || needs_modeset(crtc_state))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
crtc_state->mode_changed = true;
|
|
|
|
|
|
|
|
|
|
ret = drm_atomic_add_affected_connectors(state, crtc);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
ret = drm_atomic_add_affected_planes(state, crtc);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-01 12:50:02 +02:00
|
|
|
static int intel_modeset_checks(struct drm_atomic_state *state)
|
2015-04-21 17:13:06 +03:00
|
|
|
{
|
2015-12-10 12:33:57 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
|
|
struct drm_i915_private *dev_priv = state->dev->dev_private;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
int ret = 0, i;
|
2015-04-21 17:13:06 +03:00
|
|
|
|
2015-06-15 12:33:38 +02:00
|
|
|
if (!check_digital_port_conflicts(state)) {
|
|
|
|
|
DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
intel_state->modeset = true;
|
|
|
|
|
intel_state->active_crtcs = dev_priv->active_crtcs;
|
|
|
|
|
|
|
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
if (crtc_state->active)
|
|
|
|
|
intel_state->active_crtcs |= 1 << i;
|
|
|
|
|
else
|
|
|
|
|
intel_state->active_crtcs &= ~(1 << i);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:06 +03:00
|
|
|
/*
|
|
|
|
|
* See if the config requires any additional preparation, e.g.
|
|
|
|
|
* to adjust global state with pipes off. We need to do this
|
|
|
|
|
* here so we can get the modeset_pipe updated config for the new
|
|
|
|
|
* mode set on this crtc. For other crtcs we need to use the
|
|
|
|
|
* adjusted_mode bits in the crtc directly.
|
|
|
|
|
*/
|
2015-06-15 12:33:56 +02:00
|
|
|
if (dev_priv->display.modeset_calc_cdclk) {
|
|
|
|
|
ret = dev_priv->display.modeset_calc_cdclk(state);
|
|
|
|
|
|
2015-12-03 14:31:06 +01:00
|
|
|
if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq)
|
2015-06-15 12:33:56 +02:00
|
|
|
ret = intel_modeset_all_pipes(state);
|
|
|
|
|
|
|
|
|
|
if (ret < 0)
|
2015-04-21 17:13:06 +03:00
|
|
|
return ret;
|
2015-06-15 12:33:56 +02:00
|
|
|
} else
|
2015-12-03 14:31:06 +01:00
|
|
|
to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
|
2015-04-21 17:13:06 +03:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
intel_modeset_clear_plls(state);
|
2015-04-21 17:13:06 +03:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (IS_HASWELL(dev_priv))
|
2015-06-15 12:33:42 +02:00
|
|
|
return haswell_mode_set_planes_workaround(state);
|
2015-06-01 12:50:09 +02:00
|
|
|
|
2015-06-15 12:33:42 +02:00
|
|
|
return 0;
|
2015-06-01 12:50:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-24 15:53:18 -07:00
|
|
|
/*
|
|
|
|
|
* Handle calculation of various watermark data at the end of the atomic check
|
|
|
|
|
* phase. The code here should be run after the per-crtc and per-plane 'check'
|
|
|
|
|
* handlers to ensure that all derived state has been updated.
|
|
|
|
|
*/
|
|
|
|
|
static void calc_watermark_data(struct drm_atomic_state *state)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = state->dev;
|
|
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *cstate;
|
|
|
|
|
struct drm_plane *plane;
|
|
|
|
|
struct drm_plane_state *pstate;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Calculate watermark configuration details now that derived
|
|
|
|
|
* plane/crtc state is all properly updated.
|
|
|
|
|
*/
|
|
|
|
|
drm_for_each_crtc(crtc, dev) {
|
|
|
|
|
cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
|
|
|
|
|
crtc->state;
|
|
|
|
|
|
|
|
|
|
if (cstate->active)
|
|
|
|
|
intel_state->wm_config.num_pipes_active++;
|
|
|
|
|
}
|
|
|
|
|
drm_for_each_legacy_plane(plane, dev) {
|
|
|
|
|
pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
|
|
|
|
|
plane->state;
|
|
|
|
|
|
|
|
|
|
if (!to_intel_plane_state(pstate)->visible)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
intel_state->wm_config.sprites_enabled = true;
|
|
|
|
|
if (pstate->crtc_w != pstate->src_w >> 16 ||
|
|
|
|
|
pstate->crtc_h != pstate->src_h >> 16)
|
|
|
|
|
intel_state->wm_config.sprites_scaled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
/**
|
|
|
|
|
* intel_atomic_check - validate state object
|
|
|
|
|
* @dev: drm device
|
|
|
|
|
* @state: state to validate
|
|
|
|
|
*/
|
|
|
|
|
static int intel_atomic_check(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *state)
|
2015-06-01 12:50:02 +02:00
|
|
|
{
|
2015-09-24 15:53:18 -07:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
2015-06-01 12:50:02 +02:00
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *crtc_state;
|
|
|
|
|
int ret, i;
|
2015-06-15 12:33:50 +02:00
|
|
|
bool any_ms = false;
|
2015-06-01 12:50:02 +02:00
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
ret = drm_atomic_helper_check_modeset(dev, state);
|
2015-04-21 17:13:06 +03:00
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2015-06-01 12:50:02 +02:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
2015-07-14 12:17:40 +02:00
|
|
|
struct intel_crtc_state *pipe_config =
|
|
|
|
|
to_intel_crtc_state(crtc_state);
|
2015-07-15 14:15:51 +02:00
|
|
|
|
2015-11-16 12:49:14 +01:00
|
|
|
memset(&to_intel_crtc(crtc)->atomic, 0,
|
|
|
|
|
sizeof(struct intel_crtc_atomic_commit));
|
|
|
|
|
|
2015-07-15 14:15:51 +02:00
|
|
|
/* Catch I915_MODE_FLAG_INHERITED */
|
|
|
|
|
if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
|
|
|
|
|
crtc_state->mode_changed = true;
|
2015-07-14 12:17:40 +02:00
|
|
|
|
2015-06-15 12:33:50 +02:00
|
|
|
if (!crtc_state->enable) {
|
|
|
|
|
if (needs_modeset(crtc_state))
|
|
|
|
|
any_ms = true;
|
2015-06-01 12:50:02 +02:00
|
|
|
continue;
|
2015-06-15 12:33:50 +02:00
|
|
|
}
|
2015-06-01 12:50:02 +02:00
|
|
|
|
2015-07-15 14:15:52 +02:00
|
|
|
if (!needs_modeset(crtc_state))
|
2015-07-14 12:17:40 +02:00
|
|
|
continue;
|
|
|
|
|
|
2015-07-15 14:15:52 +02:00
|
|
|
/* FIXME: For only active_changed we shouldn't need to do any
|
|
|
|
|
* state recomputation at all. */
|
|
|
|
|
|
2015-07-15 14:15:51 +02:00
|
|
|
ret = drm_atomic_add_affected_connectors(state, crtc);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
2015-06-15 12:33:38 +02:00
|
|
|
|
2015-07-14 12:17:40 +02:00
|
|
|
ret = intel_modeset_pipe_config(crtc, pipe_config);
|
2015-06-01 12:50:02 +02:00
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2015-11-19 10:26:30 +02:00
|
|
|
if (i915.fastboot &&
|
|
|
|
|
intel_pipe_config_compare(state->dev,
|
2015-07-14 12:17:40 +02:00
|
|
|
to_intel_crtc_state(crtc->state),
|
2015-07-15 14:15:51 +02:00
|
|
|
pipe_config, true)) {
|
2015-07-15 14:15:52 +02:00
|
|
|
crtc_state->mode_changed = false;
|
2015-08-27 15:44:05 +02:00
|
|
|
to_intel_crtc_state(crtc_state)->update_pipe = true;
|
2015-07-15 14:15:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needs_modeset(crtc_state)) {
|
|
|
|
|
any_ms = true;
|
2015-07-14 12:17:40 +02:00
|
|
|
|
|
|
|
|
ret = drm_atomic_add_affected_planes(state, crtc);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2015-06-15 12:33:50 +02:00
|
|
|
|
2015-07-15 14:15:52 +02:00
|
|
|
intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
|
|
|
|
|
needs_modeset(crtc_state) ?
|
|
|
|
|
"[modeset]" : "[fastset]");
|
2015-06-01 12:50:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:50 +02:00
|
|
|
if (any_ms) {
|
|
|
|
|
ret = intel_modeset_checks(state);
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
2015-06-15 12:33:56 +02:00
|
|
|
} else
|
2015-09-24 15:53:18 -07:00
|
|
|
intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
|
2015-09-24 15:53:18 -07:00
|
|
|
|
2015-09-24 15:53:18 -07:00
|
|
|
ret = drm_atomic_helper_check_planes(state->dev, state);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
calc_watermark_data(state);
|
|
|
|
|
|
|
|
|
|
return 0;
|
2015-04-21 17:13:06 +03:00
|
|
|
}
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
static int intel_atomic_prepare_commit(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *state,
|
|
|
|
|
bool async)
|
|
|
|
|
{
|
2015-08-18 13:40:06 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
struct drm_plane_state *plane_state;
|
2015-08-18 13:40:05 +02:00
|
|
|
struct drm_crtc_state *crtc_state;
|
2015-08-18 13:40:06 +02:00
|
|
|
struct drm_plane *plane;
|
2015-08-18 13:40:05 +02:00
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
if (async) {
|
|
|
|
|
DRM_DEBUG_KMS("i915 does not yet support async commit\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
ret = intel_crtc_wait_for_pending_flips(crtc);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
2015-08-18 13:40:06 +02:00
|
|
|
|
|
|
|
|
if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
|
|
|
|
|
flush_workqueue(dev_priv->wq);
|
2015-08-18 13:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
ret = drm_atomic_helper_prepare_planes(dev, state);
|
2015-08-18 13:40:06 +02:00
|
|
|
if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) {
|
|
|
|
|
u32 reset_counter;
|
|
|
|
|
|
|
|
|
|
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
|
|
for_each_plane_in_state(state, plane, plane_state, i) {
|
|
|
|
|
struct intel_plane_state *intel_plane_state =
|
|
|
|
|
to_intel_plane_state(plane_state);
|
|
|
|
|
|
|
|
|
|
if (!intel_plane_state->wait_req)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ret = __i915_wait_request(intel_plane_state->wait_req,
|
|
|
|
|
reset_counter, true,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
|
|
/* Swallow -EIO errors to allow updates during hw lockup. */
|
|
|
|
|
if (ret == -EIO)
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
drm_atomic_helper_cleanup_planes(dev, state);
|
|
|
|
|
}
|
2015-08-18 13:40:05 +02:00
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2015-08-18 13:40:05 +02:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
/**
|
|
|
|
|
* intel_atomic_commit - commit validated state object
|
|
|
|
|
* @dev: DRM device
|
|
|
|
|
* @state: the top-level driver state object
|
|
|
|
|
* @async: asynchronous commit
|
|
|
|
|
*
|
|
|
|
|
* This function commits a top-level state object that has been validated
|
|
|
|
|
* with drm_atomic_helper_check().
|
|
|
|
|
*
|
|
|
|
|
* FIXME: Atomic modeset support for i915 is not yet complete. At the moment
|
|
|
|
|
* we can only handle plane-related operations and do not yet support
|
|
|
|
|
* asynchronous commit.
|
|
|
|
|
*
|
|
|
|
|
* RETURNS
|
|
|
|
|
* Zero for success or -errno.
|
|
|
|
|
*/
|
|
|
|
|
static int intel_atomic_commit(struct drm_device *dev,
|
|
|
|
|
struct drm_atomic_state *state,
|
|
|
|
|
bool async)
|
2012-07-02 09:56:42 +02:00
|
|
|
{
|
2015-12-10 12:33:57 +01:00
|
|
|
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-04-21 17:13:04 +03:00
|
|
|
struct drm_crtc_state *crtc_state;
|
2015-08-18 13:40:06 +02:00
|
|
|
struct drm_crtc *crtc;
|
2016-01-06 11:34:30 -08:00
|
|
|
struct intel_crtc_state *intel_cstate;
|
2015-12-10 12:33:57 +01:00
|
|
|
int ret = 0, i;
|
|
|
|
|
bool hw_check = intel_state->modeset;
|
2012-07-02 09:56:42 +02:00
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
ret = intel_atomic_prepare_commit(dev, state, async);
|
2015-08-18 13:40:06 +02:00
|
|
|
if (ret) {
|
|
|
|
|
DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
|
2015-04-21 17:13:22 +03:00
|
|
|
return ret;
|
2015-08-18 13:40:06 +02:00
|
|
|
}
|
2015-04-21 17:13:22 +03:00
|
|
|
|
2015-06-01 12:50:06 +02:00
|
|
|
drm_atomic_helper_swap_state(dev, state);
|
2015-09-24 15:53:18 -07:00
|
|
|
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
|
2015-06-01 12:50:06 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (intel_state->modeset) {
|
|
|
|
|
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
|
|
|
|
|
sizeof(intel_state->min_pixclk));
|
|
|
|
|
dev_priv->active_crtcs = intel_state->active_crtcs;
|
2015-12-03 14:31:06 +01:00
|
|
|
dev_priv->atomic_cdclk_freq = intel_state->cdclk;
|
2015-12-10 12:33:57 +01:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:13:04 +03:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
2015-06-15 12:33:52 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
2015-06-15 12:33:50 +02:00
|
|
|
if (!needs_modeset(crtc->state))
|
|
|
|
|
continue;
|
|
|
|
|
|
2015-06-15 12:33:52 +02:00
|
|
|
intel_pre_plane_update(intel_crtc);
|
2013-03-27 00:44:51 +01:00
|
|
|
|
2015-06-15 12:33:52 +02:00
|
|
|
if (crtc_state->active) {
|
|
|
|
|
intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
|
|
|
|
|
dev_priv->display.crtc_disable(crtc);
|
2015-06-15 12:33:53 +02:00
|
|
|
intel_crtc->active = false;
|
|
|
|
|
intel_disable_shared_dpll(intel_crtc);
|
2015-11-20 22:09:20 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Underruns don't always raise
|
|
|
|
|
* interrupts, so check manually.
|
|
|
|
|
*/
|
|
|
|
|
intel_check_cpu_fifo_underruns(dev_priv);
|
|
|
|
|
intel_check_pch_fifo_underruns(dev_priv);
|
2015-11-19 16:07:16 +01:00
|
|
|
|
|
|
|
|
if (!crtc->state->active)
|
|
|
|
|
intel_update_watermarks(crtc);
|
2015-06-15 12:33:52 +02:00
|
|
|
}
|
2013-03-27 00:44:50 +01:00
|
|
|
}
|
2012-07-08 19:40:39 +02:00
|
|
|
|
2012-07-10 10:42:52 +02:00
|
|
|
/* Only after disabling all output pipelines that will be changed can we
|
|
|
|
|
* update the the output configuration. */
|
2015-08-05 12:37:10 +02:00
|
|
|
intel_modeset_update_crtc_state(state);
|
2011-04-12 18:06:51 +01:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (intel_state->modeset) {
|
2015-08-05 12:37:10 +02:00
|
|
|
intel_shared_dpll_commit(state);
|
|
|
|
|
|
|
|
|
|
drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
|
2015-06-15 12:33:50 +02:00
|
|
|
modeset_update_crtc_power_domains(state);
|
2015-08-05 12:37:10 +02:00
|
|
|
}
|
2012-10-26 10:58:18 +02:00
|
|
|
|
2012-07-02 09:56:42 +02:00
|
|
|
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
|
2015-04-21 17:13:04 +03:00
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
2015-07-13 16:30:31 +02:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
bool modeset = needs_modeset(crtc->state);
|
2015-08-27 15:44:05 +02:00
|
|
|
bool update_pipe = !modeset &&
|
|
|
|
|
to_intel_crtc_state(crtc->state)->update_pipe;
|
|
|
|
|
unsigned long put_domains = 0;
|
2015-07-13 16:30:31 +02:00
|
|
|
|
2015-11-16 16:20:01 +01:00
|
|
|
if (modeset)
|
|
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
|
|
|
|
|
|
2015-07-13 16:30:31 +02:00
|
|
|
if (modeset && crtc->state->active) {
|
2015-06-15 12:33:52 +02:00
|
|
|
update_scanline_offset(to_intel_crtc(crtc));
|
|
|
|
|
dev_priv->display.crtc_enable(crtc);
|
|
|
|
|
}
|
2014-05-15 20:23:23 +03:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
if (update_pipe) {
|
|
|
|
|
put_domains = modeset_get_crtc_power_domains(crtc);
|
|
|
|
|
|
|
|
|
|
/* make sure intel_modeset_check_state runs */
|
2015-12-10 12:33:57 +01:00
|
|
|
hw_check = true;
|
2015-08-27 15:44:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:31 +02:00
|
|
|
if (!modeset)
|
|
|
|
|
intel_pre_plane_update(intel_crtc);
|
|
|
|
|
|
2015-09-23 16:29:39 +02:00
|
|
|
if (crtc->state->active &&
|
|
|
|
|
(crtc->state->planes_changed || update_pipe))
|
2015-09-23 16:29:38 +02:00
|
|
|
drm_atomic_helper_commit_planes_on_crtc(crtc_state);
|
2015-08-27 15:44:05 +02:00
|
|
|
|
|
|
|
|
if (put_domains)
|
|
|
|
|
modeset_put_power_domains(dev_priv, put_domains);
|
|
|
|
|
|
2015-07-13 16:30:31 +02:00
|
|
|
intel_post_plane_update(intel_crtc);
|
2015-11-16 16:20:01 +01:00
|
|
|
|
|
|
|
|
if (modeset)
|
|
|
|
|
intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
|
2014-05-15 20:23:23 +03:00
|
|
|
}
|
2012-07-02 09:56:42 +02:00
|
|
|
|
|
|
|
|
/* FIXME: add subpixel order */
|
2015-03-20 16:18:03 +02:00
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
drm_atomic_helper_wait_for_vblanks(dev, state);
|
2015-08-18 13:40:05 +02:00
|
|
|
|
2016-01-06 11:34:30 -08:00
|
|
|
/*
|
|
|
|
|
* Now that the vblank has passed, we can go ahead and program the
|
|
|
|
|
* optimal watermarks on platforms that need two-step watermark
|
|
|
|
|
* programming.
|
|
|
|
|
*
|
|
|
|
|
* TODO: Move this (and other cleanup) to an async worker eventually.
|
|
|
|
|
*/
|
|
|
|
|
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
|
|
intel_cstate = to_intel_crtc_state(crtc->state);
|
|
|
|
|
|
|
|
|
|
if (dev_priv->display.optimize_watermarks)
|
|
|
|
|
dev_priv->display.optimize_watermarks(intel_cstate);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2015-04-21 17:13:22 +03:00
|
|
|
drm_atomic_helper_cleanup_planes(dev, state);
|
2015-08-18 13:40:05 +02:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
2015-04-21 17:13:20 +03:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
if (hw_check)
|
2015-08-05 12:37:00 +02:00
|
|
|
intel_modeset_check_state(dev, state);
|
|
|
|
|
|
|
|
|
|
drm_atomic_state_free(state);
|
2013-04-11 20:22:50 +02:00
|
|
|
|
2015-07-13 16:30:30 +02:00
|
|
|
return 0;
|
2014-11-05 14:26:06 -08:00
|
|
|
}
|
|
|
|
|
|
2012-12-19 16:08:43 +00:00
|
|
|
void intel_crtc_restore_mode(struct drm_crtc *crtc)
|
|
|
|
|
{
|
2015-03-20 16:18:03 +02:00
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
|
|
struct drm_atomic_state *state;
|
2015-07-14 16:19:12 +02:00
|
|
|
struct drm_crtc_state *crtc_state;
|
2015-04-21 17:13:20 +03:00
|
|
|
int ret;
|
2015-03-20 16:18:03 +02:00
|
|
|
|
|
|
|
|
state = drm_atomic_state_alloc(dev);
|
|
|
|
|
if (!state) {
|
2015-07-14 16:19:12 +02:00
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] crtc restore failed, out of memory",
|
2015-03-20 16:18:03 +02:00
|
|
|
crtc->base.id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:19:12 +02:00
|
|
|
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
2015-03-20 16:18:03 +02:00
|
|
|
|
2015-07-14 16:19:12 +02:00
|
|
|
retry:
|
|
|
|
|
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
|
|
|
ret = PTR_ERR_OR_ZERO(crtc_state);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
if (!crtc_state->active)
|
|
|
|
|
goto out;
|
2015-03-20 16:18:03 +02:00
|
|
|
|
2015-07-14 16:19:12 +02:00
|
|
|
crtc_state->mode_changed = true;
|
2015-07-13 16:30:30 +02:00
|
|
|
ret = drm_atomic_commit(state);
|
2015-03-20 16:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:19:12 +02:00
|
|
|
if (ret == -EDEADLK) {
|
|
|
|
|
drm_atomic_state_clear(state);
|
|
|
|
|
drm_modeset_backoff(state->acquire_ctx);
|
|
|
|
|
goto retry;
|
2015-06-16 11:49:45 +03:00
|
|
|
}
|
2015-04-21 17:13:01 +03:00
|
|
|
|
2015-04-21 17:13:20 +03:00
|
|
|
if (ret)
|
2015-07-14 16:19:12 +02:00
|
|
|
out:
|
2015-04-21 17:13:20 +03:00
|
|
|
drm_atomic_state_free(state);
|
2012-12-19 16:08:43 +00:00
|
|
|
}
|
|
|
|
|
|
2012-07-08 22:08:04 +02:00
|
|
|
#undef for_each_intel_crtc_masked
|
|
|
|
|
|
2011-04-12 18:06:51 +01:00
|
|
|
static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|
|
|
|
.gamma_set = intel_crtc_gamma_set,
|
2015-07-13 16:30:30 +02:00
|
|
|
.set_config = drm_atomic_helper_set_config,
|
2011-04-12 18:06:51 +01:00
|
|
|
.destroy = intel_crtc_destroy,
|
|
|
|
|
.page_flip = intel_crtc_page_flip,
|
2015-01-21 16:35:47 -08:00
|
|
|
.atomic_duplicate_state = intel_crtc_duplicate_state,
|
|
|
|
|
.atomic_destroy_state = intel_crtc_destroy_state,
|
2011-04-12 18:06:51 +01:00
|
|
|
};
|
|
|
|
|
|
2013-06-05 13:34:16 +02:00
|
|
|
static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_shared_dpll *pll,
|
|
|
|
|
struct intel_dpll_hw_state *hw_state)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2013-06-05 13:34:16 +02:00
|
|
|
uint32_t val;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
|
2014-07-04 11:27:38 -03:00
|
|
|
return false;
|
|
|
|
|
|
2013-06-05 13:34:16 +02:00
|
|
|
val = I915_READ(PCH_DPLL(pll->id));
|
2013-06-05 13:34:20 +02:00
|
|
|
hw_state->dpll = val;
|
|
|
|
|
hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
|
|
|
|
|
hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
|
2013-06-05 13:34:16 +02:00
|
|
|
|
|
|
|
|
return val & DPLL_VCO_ENABLE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:23 +02:00
|
|
|
static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_shared_dpll *pll)
|
|
|
|
|
{
|
2014-10-29 11:32:32 +02:00
|
|
|
I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
|
|
|
|
|
I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
|
2013-06-05 13:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:14 +02:00
|
|
|
static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_shared_dpll *pll)
|
|
|
|
|
{
|
|
|
|
|
/* PCH refclock must be enabled first */
|
2014-01-08 11:12:28 -02:00
|
|
|
ibx_assert_pch_refclk_enabled(dev_priv);
|
2013-06-05 13:34:14 +02:00
|
|
|
|
2014-10-29 11:32:32 +02:00
|
|
|
I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
|
2013-06-05 13:34:23 +02:00
|
|
|
|
|
|
|
|
/* Wait for the clocks to stabilize. */
|
|
|
|
|
POSTING_READ(PCH_DPLL(pll->id));
|
|
|
|
|
udelay(150);
|
|
|
|
|
|
|
|
|
|
/* The pixel multiplier can only be updated once the
|
|
|
|
|
* DPLL is enabled and the clocks are stable.
|
|
|
|
|
*
|
|
|
|
|
* So write it again.
|
|
|
|
|
*/
|
2014-10-29 11:32:32 +02:00
|
|
|
I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
|
2013-06-05 13:34:23 +02:00
|
|
|
POSTING_READ(PCH_DPLL(pll->id));
|
2013-06-05 13:34:14 +02:00
|
|
|
udelay(200);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct intel_shared_dpll *pll)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
|
|
/* Make sure no transcoder isn't still depending on us. */
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2013-06-05 13:34:14 +02:00
|
|
|
if (intel_crtc_to_shared_dpll(crtc) == pll)
|
|
|
|
|
assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
|
2012-04-20 17:11:53 +01:00
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:23 +02:00
|
|
|
I915_WRITE(PCH_DPLL(pll->id), 0);
|
|
|
|
|
POSTING_READ(PCH_DPLL(pll->id));
|
2013-06-05 13:34:14 +02:00
|
|
|
udelay(200);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:12 +02:00
|
|
|
static char *ibx_pch_dpll_names[] = {
|
|
|
|
|
"PCH DPLL A",
|
|
|
|
|
"PCH DPLL B",
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-05 13:34:11 +02:00
|
|
|
static void ibx_pch_dpll_init(struct drm_device *dev)
|
2012-04-20 17:11:53 +01:00
|
|
|
{
|
2013-06-05 13:34:14 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2012-04-20 17:11:53 +01:00
|
|
|
int i;
|
|
|
|
|
|
2013-06-05 13:34:11 +02:00
|
|
|
dev_priv->num_shared_dpll = 2;
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2013-06-05 13:34:06 +02:00
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
2013-06-05 13:34:12 +02:00
|
|
|
dev_priv->shared_dplls[i].id = i;
|
|
|
|
|
dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
|
2013-06-05 13:34:23 +02:00
|
|
|
dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
|
2013-06-05 13:34:14 +02:00
|
|
|
dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
|
|
|
|
|
dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
|
2013-06-05 13:34:16 +02:00
|
|
|
dev_priv->shared_dplls[i].get_hw_state =
|
|
|
|
|
ibx_pch_dpll_get_hw_state;
|
2012-04-20 17:11:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:11 +02:00
|
|
|
static void intel_shared_dpll_init(struct drm_device *dev)
|
|
|
|
|
{
|
2013-06-05 13:34:14 +02:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2013-06-05 13:34:11 +02:00
|
|
|
|
2014-06-25 22:01:57 +03:00
|
|
|
if (HAS_DDI(dev))
|
|
|
|
|
intel_ddi_pll_init(dev);
|
|
|
|
|
else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
2013-06-05 13:34:11 +02:00
|
|
|
ibx_pch_dpll_init(dev);
|
|
|
|
|
else
|
|
|
|
|
dev_priv->num_shared_dpll = 0;
|
|
|
|
|
|
|
|
|
|
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 15:40:14 -08:00
|
|
|
/**
|
|
|
|
|
* intel_prepare_plane_fb - Prepare fb for usage on plane
|
|
|
|
|
* @plane: drm plane to prepare for
|
|
|
|
|
* @fb: framebuffer to prepare for presentation
|
|
|
|
|
*
|
|
|
|
|
* Prepares a framebuffer for usage on a display plane. Generally this
|
|
|
|
|
* involves pinning the underlying object and updating the frontbuffer tracking
|
|
|
|
|
* bits. Some older platforms need special physical address handling for
|
|
|
|
|
* cursor planes.
|
|
|
|
|
*
|
2015-08-18 13:40:05 +02:00
|
|
|
* Must be called with struct_mutex held.
|
|
|
|
|
*
|
2014-12-01 15:40:14 -08:00
|
|
|
* Returns 0 on success, negative error code on failure.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
intel_prepare_plane_fb(struct drm_plane *plane,
|
2015-03-03 14:22:31 +00:00
|
|
|
const struct drm_plane_state *new_state)
|
2014-05-29 08:06:54 -07:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = plane->dev;
|
2015-09-02 10:42:40 +02:00
|
|
|
struct drm_framebuffer *fb = new_state->fb;
|
2014-12-01 15:40:14 -08:00
|
|
|
struct intel_plane *intel_plane = to_intel_plane(plane);
|
|
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
2015-09-23 13:27:08 +02:00
|
|
|
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
|
2014-12-01 15:40:14 -08:00
|
|
|
int ret = 0;
|
2014-05-29 08:06:54 -07:00
|
|
|
|
2015-09-23 13:27:08 +02:00
|
|
|
if (!obj && !old_obj)
|
2014-05-29 08:06:54 -07:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-18 13:40:05 +02:00
|
|
|
if (old_obj) {
|
|
|
|
|
struct drm_crtc_state *crtc_state =
|
|
|
|
|
drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
|
|
|
|
|
|
|
|
|
|
/* 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. Note that we rely on userspace rendering
|
|
|
|
|
* into the buffer attached to the pipe they are waiting
|
|
|
|
|
* on. If not, userspace generates a GPU hang with IPEHR
|
|
|
|
|
* point to the MI_WAIT_FOR_EVENT.
|
|
|
|
|
*
|
|
|
|
|
* This should only fail upon a hung GPU, in which case we
|
|
|
|
|
* can safely continue.
|
|
|
|
|
*/
|
|
|
|
|
if (needs_modeset(crtc_state))
|
|
|
|
|
ret = i915_gem_object_wait_rendering(old_obj, true);
|
|
|
|
|
|
|
|
|
|
/* Swallow -EIO errors to allow updates during hw lockup. */
|
|
|
|
|
if (ret && ret != -EIO)
|
2015-08-18 13:40:05 +02:00
|
|
|
return ret;
|
2015-08-18 13:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-25 18:43:39 -08:00
|
|
|
/* For framebuffer backed by dmabuf, wait for fence */
|
|
|
|
|
if (obj && obj->base.dma_buf) {
|
|
|
|
|
ret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
|
|
|
|
|
false, true,
|
|
|
|
|
MAX_SCHEDULE_TIMEOUT);
|
|
|
|
|
if (ret == -ERESTARTSYS)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
WARN_ON(ret < 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-23 13:27:08 +02:00
|
|
|
if (!obj) {
|
|
|
|
|
ret = 0;
|
|
|
|
|
} else if (plane->type == DRM_PLANE_TYPE_CURSOR &&
|
2014-12-01 15:40:14 -08:00
|
|
|
INTEL_INFO(dev)->cursor_needs_physical) {
|
|
|
|
|
int align = IS_I830(dev) ? 16 * 1024 : 256;
|
|
|
|
|
ret = i915_gem_object_attach_phys(obj, align);
|
|
|
|
|
if (ret)
|
|
|
|
|
DRM_DEBUG_KMS("failed to attach phys object\n");
|
|
|
|
|
} else {
|
2015-08-18 13:40:06 +02:00
|
|
|
ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
|
2014-12-01 15:40:14 -08:00
|
|
|
}
|
2014-05-29 08:06:54 -07:00
|
|
|
|
2015-08-18 13:40:06 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
|
if (obj) {
|
|
|
|
|
struct intel_plane_state *plane_state =
|
|
|
|
|
to_intel_plane_state(new_state);
|
|
|
|
|
|
|
|
|
|
i915_gem_request_assign(&plane_state->wait_req,
|
|
|
|
|
obj->last_write_req);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-24 21:59:34 +03:00
|
|
|
i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
|
2015-08-18 13:40:06 +02:00
|
|
|
}
|
2014-08-08 21:51:11 +03:00
|
|
|
|
2014-12-01 15:40:14 -08:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-02 07:45:25 -08:00
|
|
|
/**
|
|
|
|
|
* intel_cleanup_plane_fb - Cleans up an fb after plane use
|
|
|
|
|
* @plane: drm plane to clean up for
|
|
|
|
|
* @fb: old framebuffer that was on plane
|
|
|
|
|
*
|
|
|
|
|
* Cleans up a framebuffer that has just been removed from a plane.
|
2015-08-18 13:40:05 +02:00
|
|
|
*
|
|
|
|
|
* Must be called with struct_mutex held.
|
2014-12-02 07:45:25 -08:00
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
intel_cleanup_plane_fb(struct drm_plane *plane,
|
2015-03-03 14:22:31 +00:00
|
|
|
const struct drm_plane_state *old_state)
|
2014-12-02 07:45:25 -08:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = plane->dev;
|
2015-09-23 13:27:08 +02:00
|
|
|
struct intel_plane *intel_plane = to_intel_plane(plane);
|
2015-08-18 13:40:06 +02:00
|
|
|
struct intel_plane_state *old_intel_state;
|
2015-09-23 13:27:08 +02:00
|
|
|
struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
|
|
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
|
2014-12-02 07:45:25 -08:00
|
|
|
|
2015-08-18 13:40:06 +02:00
|
|
|
old_intel_state = to_intel_plane_state(old_state);
|
|
|
|
|
|
2015-09-23 13:27:08 +02:00
|
|
|
if (!obj && !old_obj)
|
2014-12-02 07:45:25 -08:00
|
|
|
return;
|
|
|
|
|
|
2015-09-23 13:27:08 +02:00
|
|
|
if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
|
|
|
|
|
!INTEL_INFO(dev)->cursor_needs_physical))
|
2015-09-02 10:42:40 +02:00
|
|
|
intel_unpin_fb_obj(old_state->fb, old_state);
|
2015-09-23 13:27:08 +02:00
|
|
|
|
|
|
|
|
/* prepare_fb aborted? */
|
|
|
|
|
if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
|
|
|
|
|
(obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit)))
|
|
|
|
|
i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
|
2015-08-18 13:40:06 +02:00
|
|
|
|
|
|
|
|
i915_gem_request_assign(&old_intel_state->wait_req, NULL);
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
2015-04-27 13:48:39 -07:00
|
|
|
int
|
|
|
|
|
skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
|
|
|
|
|
{
|
|
|
|
|
int max_scale;
|
|
|
|
|
struct drm_device *dev;
|
|
|
|
|
struct drm_i915_private *dev_priv;
|
|
|
|
|
int crtc_clock, cdclk;
|
|
|
|
|
|
2015-11-24 11:29:02 +01:00
|
|
|
if (!intel_crtc || !crtc_state->base.enable)
|
2015-04-27 13:48:39 -07:00
|
|
|
return DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
|
|
|
|
|
dev = intel_crtc->base.dev;
|
|
|
|
|
dev_priv = dev->dev_private;
|
|
|
|
|
crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
|
2015-06-15 12:33:56 +02:00
|
|
|
cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
|
2015-04-27 13:48:39 -07:00
|
|
|
|
2015-10-20 17:17:07 +01:00
|
|
|
if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
|
2015-04-27 13:48:39 -07:00
|
|
|
return DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* skl max scale is lower of:
|
|
|
|
|
* close to 3 but not 3, -1 is for that purpose
|
|
|
|
|
* or
|
|
|
|
|
* cdclk/crtc_clock
|
|
|
|
|
*/
|
|
|
|
|
max_scale = min((1 << 16) * 3 - 1, (1 << 8) * ((cdclk << 8) / crtc_clock));
|
|
|
|
|
|
|
|
|
|
return max_scale;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
static int
|
2014-09-05 17:04:49 -03:00
|
|
|
intel_check_primary_plane(struct drm_plane *plane,
|
2015-06-15 12:33:46 +02:00
|
|
|
struct intel_crtc_state *crtc_state,
|
2014-09-05 17:04:49 -03:00
|
|
|
struct intel_plane_state *state)
|
|
|
|
|
{
|
2014-12-01 15:40:13 -08:00
|
|
|
struct drm_crtc *crtc = state->base.crtc;
|
|
|
|
|
struct drm_framebuffer *fb = state->base.fb;
|
2015-04-27 13:48:39 -07:00
|
|
|
int min_scale = DRM_PLANE_HELPER_NO_SCALING;
|
2015-06-15 12:33:46 +02:00
|
|
|
int max_scale = DRM_PLANE_HELPER_NO_SCALING;
|
|
|
|
|
bool can_position = false;
|
2014-05-29 08:06:54 -07:00
|
|
|
|
2015-06-15 12:33:46 +02:00
|
|
|
/* use scaler when colorkey is not required */
|
|
|
|
|
if (INTEL_INFO(plane->dev)->gen >= 9 &&
|
2015-06-15 12:33:54 +02:00
|
|
|
state->ckey.flags == I915_SET_COLORKEY_NONE) {
|
2015-06-15 12:33:46 +02:00
|
|
|
min_scale = 1;
|
|
|
|
|
max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
|
2015-04-10 14:37:28 +05:30
|
|
|
can_position = true;
|
2015-04-27 13:48:39 -07:00
|
|
|
}
|
2015-04-10 14:37:28 +05:30
|
|
|
|
2015-06-15 12:33:46 +02:00
|
|
|
return drm_plane_helper_check_update(plane, crtc, fb, &state->src,
|
|
|
|
|
&state->dst, &state->clip,
|
2015-06-15 12:33:44 +02:00
|
|
|
min_scale, max_scale,
|
|
|
|
|
can_position, true,
|
|
|
|
|
&state->visible);
|
2014-10-24 14:51:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
intel_commit_primary_plane(struct drm_plane *plane,
|
|
|
|
|
struct intel_plane_state *state)
|
|
|
|
|
{
|
2014-12-01 15:40:13 -08:00
|
|
|
struct drm_crtc *crtc = state->base.crtc;
|
|
|
|
|
struct drm_framebuffer *fb = state->base.fb;
|
|
|
|
|
struct drm_device *dev = plane->dev;
|
2014-10-24 14:51:31 +01:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2014-12-23 10:41:52 -08:00
|
|
|
crtc = crtc ? crtc : plane->crtc;
|
2014-09-24 14:20:22 -03:00
|
|
|
|
2015-09-10 16:07:56 +02:00
|
|
|
dev_priv->display.update_primary_plane(crtc, fb,
|
|
|
|
|
state->src.x1 >> 16,
|
|
|
|
|
state->src.y1 >> 16);
|
2014-05-29 08:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
2015-04-21 17:12:51 +03:00
|
|
|
static void
|
|
|
|
|
intel_disable_primary_plane(struct drm_plane *plane,
|
2015-06-15 12:33:47 +02:00
|
|
|
struct drm_crtc *crtc)
|
2015-04-21 17:12:51 +03:00
|
|
|
{
|
|
|
|
|
struct drm_device *dev = plane->dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-21 13:28:58 +02:00
|
|
|
static void intel_begin_crtc_commit(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_crtc_state *old_crtc_state)
|
2014-09-05 17:04:49 -03:00
|
|
|
{
|
2014-12-24 07:59:06 -08:00
|
|
|
struct drm_device *dev = crtc->dev;
|
2014-09-05 17:04:49 -03:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2015-08-27 15:44:05 +02:00
|
|
|
struct intel_crtc_state *old_intel_state =
|
|
|
|
|
to_intel_crtc_state(old_crtc_state);
|
|
|
|
|
bool modeset = needs_modeset(crtc->state);
|
2014-09-05 17:04:49 -03:00
|
|
|
|
2014-12-23 10:41:50 -08:00
|
|
|
/* Perform vblank evasion around commit operation */
|
2015-09-23 16:29:38 +02:00
|
|
|
intel_pipe_update_start(intel_crtc);
|
2015-06-15 12:33:48 +02:00
|
|
|
|
2015-08-27 15:44:05 +02:00
|
|
|
if (modeset)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (to_intel_crtc_state(crtc->state)->update_pipe)
|
|
|
|
|
intel_update_pipe_config(intel_crtc, old_intel_state);
|
|
|
|
|
else if (INTEL_INFO(dev)->gen >= 9)
|
2015-06-15 12:33:48 +02:00
|
|
|
skl_detach_scalers(intel_crtc);
|
2014-12-24 07:59:06 -08:00
|
|
|
}
|
|
|
|
|
|
2015-07-21 13:28:58 +02:00
|
|
|
static void intel_finish_crtc_commit(struct drm_crtc *crtc,
|
|
|
|
|
struct drm_crtc_state *old_crtc_state)
|
2014-12-24 07:59:06 -08:00
|
|
|
{
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
2015-09-23 16:29:38 +02:00
|
|
|
intel_pipe_update_end(intel_crtc);
|
2014-09-05 17:04:49 -03:00
|
|
|
}
|
|
|
|
|
|
2014-12-04 10:27:42 -08:00
|
|
|
/**
|
2014-12-23 10:41:51 -08:00
|
|
|
* intel_plane_destroy - destroy a plane
|
|
|
|
|
* @plane: plane to destroy
|
2014-12-04 10:27:42 -08:00
|
|
|
*
|
2014-12-23 10:41:51 -08:00
|
|
|
* Common destruction function for all types of planes (primary, cursor,
|
|
|
|
|
* sprite).
|
2014-12-04 10:27:42 -08:00
|
|
|
*/
|
2014-12-23 10:41:51 -08:00
|
|
|
void intel_plane_destroy(struct drm_plane *plane)
|
2014-05-29 08:06:54 -07:00
|
|
|
{
|
|
|
|
|
struct intel_plane *intel_plane = to_intel_plane(plane);
|
|
|
|
|
drm_plane_cleanup(plane);
|
|
|
|
|
kfree(intel_plane);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 16:35:42 -08:00
|
|
|
const struct drm_plane_funcs intel_plane_funcs = {
|
2015-04-08 18:56:53 -07:00
|
|
|
.update_plane = drm_atomic_helper_update_plane,
|
|
|
|
|
.disable_plane = drm_atomic_helper_disable_plane,
|
2014-06-10 08:28:13 -07:00
|
|
|
.destroy = intel_plane_destroy,
|
2015-01-21 16:35:48 -08:00
|
|
|
.set_property = drm_atomic_helper_plane_set_property,
|
2015-01-21 16:35:43 -08:00
|
|
|
.atomic_get_property = intel_plane_atomic_get_property,
|
|
|
|
|
.atomic_set_property = intel_plane_atomic_set_property,
|
2014-12-23 10:41:52 -08:00
|
|
|
.atomic_duplicate_state = intel_plane_duplicate_state,
|
|
|
|
|
.atomic_destroy_state = intel_plane_destroy_state,
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
|
|
|
|
|
int pipe)
|
|
|
|
|
{
|
|
|
|
|
struct intel_plane *primary;
|
2015-01-21 16:35:41 -08:00
|
|
|
struct intel_plane_state *state;
|
2014-05-29 08:06:54 -07:00
|
|
|
const uint32_t *intel_primary_formats;
|
2015-08-12 16:54:28 +02:00
|
|
|
unsigned int num_formats;
|
2014-05-29 08:06:54 -07:00
|
|
|
|
|
|
|
|
primary = kzalloc(sizeof(*primary), GFP_KERNEL);
|
|
|
|
|
if (primary == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2015-01-21 16:35:41 -08:00
|
|
|
state = intel_create_plane_state(&primary->base);
|
|
|
|
|
if (!state) {
|
2014-12-23 10:41:52 -08:00
|
|
|
kfree(primary);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-01-21 16:35:41 -08:00
|
|
|
primary->base.state = &state->base;
|
2014-12-23 10:41:52 -08:00
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
primary->can_scale = false;
|
|
|
|
|
primary->max_downscale = 1;
|
2015-04-27 13:48:39 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
primary->can_scale = true;
|
2015-05-11 14:35:47 -07:00
|
|
|
state->scaler_id = -1;
|
2015-04-27 13:48:39 -07:00
|
|
|
}
|
2014-05-29 08:06:54 -07:00
|
|
|
primary->pipe = pipe;
|
|
|
|
|
primary->plane = pipe;
|
2015-06-24 21:59:34 +03:00
|
|
|
primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
|
2014-12-01 15:40:16 -08:00
|
|
|
primary->check_plane = intel_check_primary_plane;
|
|
|
|
|
primary->commit_plane = intel_commit_primary_plane;
|
2015-04-21 17:12:51 +03:00
|
|
|
primary->disable_plane = intel_disable_primary_plane;
|
2014-05-29 08:06:54 -07:00
|
|
|
if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
|
|
|
|
|
primary->plane = !pipe;
|
|
|
|
|
|
2015-05-19 12:29:16 +01:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
intel_primary_formats = skl_primary_formats;
|
|
|
|
|
num_formats = ARRAY_SIZE(skl_primary_formats);
|
|
|
|
|
} else if (INTEL_INFO(dev)->gen >= 4) {
|
2015-05-12 16:13:18 +01:00
|
|
|
intel_primary_formats = i965_primary_formats;
|
|
|
|
|
num_formats = ARRAY_SIZE(i965_primary_formats);
|
2015-05-19 12:29:16 +01:00
|
|
|
} else {
|
|
|
|
|
intel_primary_formats = i8xx_primary_formats;
|
|
|
|
|
num_formats = ARRAY_SIZE(i8xx_primary_formats);
|
2014-05-29 08:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
drm_universal_plane_init(dev, &primary->base, 0,
|
2015-01-21 16:35:42 -08:00
|
|
|
&intel_plane_funcs,
|
2014-05-29 08:06:54 -07:00
|
|
|
intel_primary_formats, num_formats,
|
|
|
|
|
DRM_PLANE_TYPE_PRIMARY);
|
2014-08-22 14:06:04 +05:30
|
|
|
|
2015-04-10 14:37:29 +05:30
|
|
|
if (INTEL_INFO(dev)->gen >= 4)
|
|
|
|
|
intel_create_rotation_property(dev, primary);
|
2014-08-22 14:06:04 +05:30
|
|
|
|
2014-12-23 10:41:52 -08:00
|
|
|
drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
return &primary->base;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-10 14:37:29 +05:30
|
|
|
void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
|
|
|
|
|
{
|
|
|
|
|
if (!dev->mode_config.rotation_property) {
|
|
|
|
|
unsigned long flags = BIT(DRM_ROTATE_0) |
|
|
|
|
|
BIT(DRM_ROTATE_180);
|
|
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
|
|
|
|
flags |= BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270);
|
|
|
|
|
|
|
|
|
|
dev->mode_config.rotation_property =
|
|
|
|
|
drm_mode_create_rotation_property(dev, flags);
|
|
|
|
|
}
|
|
|
|
|
if (dev->mode_config.rotation_property)
|
|
|
|
|
drm_object_attach_property(&plane->base.base,
|
|
|
|
|
dev->mode_config.rotation_property,
|
|
|
|
|
plane->base.state->rotation);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 08:28:13 -07:00
|
|
|
static int
|
2014-09-05 17:22:31 -03:00
|
|
|
intel_check_cursor_plane(struct drm_plane *plane,
|
2015-06-15 12:33:46 +02:00
|
|
|
struct intel_crtc_state *crtc_state,
|
2014-09-05 17:22:31 -03:00
|
|
|
struct intel_plane_state *state)
|
2014-06-10 08:28:13 -07:00
|
|
|
{
|
2015-06-15 12:33:46 +02:00
|
|
|
struct drm_crtc *crtc = crtc_state->base.crtc;
|
2014-12-01 15:40:13 -08:00
|
|
|
struct drm_framebuffer *fb = state->base.fb;
|
2014-09-24 14:20:24 -03:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
drm/i915: Workaround CHV pipe C cursor fail
Turns out CHV pipe C was glued on somewhat poorly, and there's something
wrong with the cursor. If the cursor straddles the left screen edge,
and is then moved away from the edge or disabled, the pipe will often
underrun. If enough underruns are triggered quickly enough the pipe
will fall over and die (it just scans out a solid color and reports
a constant underrun). We need to turn the disp2d power well off and
on again to recover the pipe.
None of that is very nice for the user, so let's just refuse to place
the cursor in the compromised position. The ddx appears to fall back
to swcursor when the ioctl returns an error, so theoretically there's
no loss of functionality for the user (discounting swcursor bugs).
I suppose most cursors images actually have the hotspot not exactly
at 0,0 so under typical conditions the fallback will in fact kick in
as soon as the cursor touches the left edge of the screen.
Any atomic compositor should anyway be prepared to fall back to
GPU composition when things don't work out, so there should be no
problem with those.
Other things that I tried to solve this include flipping all
display related clock gating knobs I could find, increasing the
minimum gtt alignment all the way up to 512k. I also tried to see
if there are more specific screen coordinates that hit the bug, but
the findings were somewhat inconclusive. Sometimes the failures
happen almost across the whole left edge, sometimes more at the very
top and around the bottom half. I wasn't able to find any real pattern
to these variations, so it seems our only choice is to just refuse
to straddle the left screen edge at all.
Cc: stable@vger.kernel.org
Cc: Jason Plum <max@warheads.net>
Testcase: igt/kms_chv_cursor_fail
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92826
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1450459479-16286-1-git-send-email-ville.syrjala@linux.intel.com
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-18 19:24:39 +02:00
|
|
|
enum pipe pipe = to_intel_plane(plane)->pipe;
|
2014-09-24 14:20:24 -03:00
|
|
|
unsigned stride;
|
|
|
|
|
int ret;
|
2014-06-10 08:28:13 -07:00
|
|
|
|
2015-06-15 12:33:46 +02:00
|
|
|
ret = drm_plane_helper_check_update(plane, crtc, fb, &state->src,
|
|
|
|
|
&state->dst, &state->clip,
|
2014-06-10 08:28:13 -07:00
|
|
|
DRM_PLANE_HELPER_NO_SCALING,
|
|
|
|
|
DRM_PLANE_HELPER_NO_SCALING,
|
2014-09-05 17:22:31 -03:00
|
|
|
true, true, &state->visible);
|
2014-09-24 14:20:24 -03:00
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
/* if we want to turn off the cursor ignore width and height */
|
|
|
|
|
if (!obj)
|
2015-06-15 12:33:44 +02:00
|
|
|
return 0;
|
2014-09-24 14:20:24 -03:00
|
|
|
|
|
|
|
|
/* Check for which cursor types we support */
|
2015-06-15 12:33:46 +02:00
|
|
|
if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) {
|
2014-12-23 10:41:52 -08:00
|
|
|
DRM_DEBUG("Cursor dimension %dx%d not supported\n",
|
|
|
|
|
state->base.crtc_w, state->base.crtc_h);
|
2014-09-24 14:20:24 -03:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 10:41:52 -08:00
|
|
|
stride = roundup_pow_of_two(state->base.crtc_w) * 4;
|
|
|
|
|
if (obj->base.size < stride * state->base.crtc_h) {
|
2014-09-24 14:20:24 -03:00
|
|
|
DRM_DEBUG_KMS("buffer is too small\n");
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-09 21:08:37 +02:00
|
|
|
if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
|
2014-09-24 14:20:24 -03:00
|
|
|
DRM_DEBUG_KMS("cursor cannot be tiled\n");
|
2015-06-15 12:33:44 +02:00
|
|
|
return -EINVAL;
|
2014-12-24 07:59:06 -08:00
|
|
|
}
|
|
|
|
|
|
drm/i915: Workaround CHV pipe C cursor fail
Turns out CHV pipe C was glued on somewhat poorly, and there's something
wrong with the cursor. If the cursor straddles the left screen edge,
and is then moved away from the edge or disabled, the pipe will often
underrun. If enough underruns are triggered quickly enough the pipe
will fall over and die (it just scans out a solid color and reports
a constant underrun). We need to turn the disp2d power well off and
on again to recover the pipe.
None of that is very nice for the user, so let's just refuse to place
the cursor in the compromised position. The ddx appears to fall back
to swcursor when the ioctl returns an error, so theoretically there's
no loss of functionality for the user (discounting swcursor bugs).
I suppose most cursors images actually have the hotspot not exactly
at 0,0 so under typical conditions the fallback will in fact kick in
as soon as the cursor touches the left edge of the screen.
Any atomic compositor should anyway be prepared to fall back to
GPU composition when things don't work out, so there should be no
problem with those.
Other things that I tried to solve this include flipping all
display related clock gating knobs I could find, increasing the
minimum gtt alignment all the way up to 512k. I also tried to see
if there are more specific screen coordinates that hit the bug, but
the findings were somewhat inconclusive. Sometimes the failures
happen almost across the whole left edge, sometimes more at the very
top and around the bottom half. I wasn't able to find any real pattern
to these variations, so it seems our only choice is to just refuse
to straddle the left screen edge at all.
Cc: stable@vger.kernel.org
Cc: Jason Plum <max@warheads.net>
Testcase: igt/kms_chv_cursor_fail
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92826
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1450459479-16286-1-git-send-email-ville.syrjala@linux.intel.com
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-18 19:24:39 +02:00
|
|
|
/*
|
|
|
|
|
* There's something wrong with the cursor on CHV pipe C.
|
|
|
|
|
* If it straddles the left edge of the screen then
|
|
|
|
|
* moving it away from the edge or disabling it often
|
|
|
|
|
* results in a pipe underrun, and often that can lead to
|
|
|
|
|
* dead pipe (constant underrun reported, and it scans
|
|
|
|
|
* out just a solid color). To recover from that, the
|
|
|
|
|
* display power well must be turned off and on again.
|
|
|
|
|
* Refuse the put the cursor into that compromised position.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
|
|
|
|
|
state->visible && state->base.crtc_x < 0) {
|
|
|
|
|
DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-15 12:33:44 +02:00
|
|
|
return 0;
|
2014-09-05 17:22:31 -03:00
|
|
|
}
|
2014-06-10 08:28:13 -07:00
|
|
|
|
2015-04-21 17:12:51 +03:00
|
|
|
static void
|
|
|
|
|
intel_disable_cursor_plane(struct drm_plane *plane,
|
2015-06-15 12:33:47 +02:00
|
|
|
struct drm_crtc *crtc)
|
2015-04-21 17:12:51 +03:00
|
|
|
{
|
2016-01-07 11:54:09 +01:00
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
|
|
|
|
intel_crtc->cursor_addr = 0;
|
2016-01-07 11:54:10 +01:00
|
|
|
intel_crtc_update_cursor(crtc, NULL);
|
2015-04-21 17:12:51 +03:00
|
|
|
}
|
|
|
|
|
|
2014-12-01 15:40:12 -08:00
|
|
|
static void
|
2016-01-07 11:54:10 +01:00
|
|
|
intel_update_cursor_plane(struct drm_plane *plane,
|
|
|
|
|
const struct intel_crtc_state *crtc_state,
|
|
|
|
|
const struct intel_plane_state *state)
|
2014-09-05 17:22:31 -03:00
|
|
|
{
|
2016-01-07 11:54:10 +01:00
|
|
|
struct drm_crtc *crtc = crtc_state->base.crtc;
|
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
2014-12-23 10:41:52 -08:00
|
|
|
struct drm_device *dev = plane->dev;
|
2014-12-01 15:40:13 -08:00
|
|
|
struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
|
2014-12-01 15:40:10 -08:00
|
|
|
uint32_t addr;
|
2014-09-05 17:22:31 -03:00
|
|
|
|
2014-12-01 15:40:12 -08:00
|
|
|
if (!obj)
|
2014-12-01 15:40:10 -08:00
|
|
|
addr = 0;
|
2014-12-01 15:40:12 -08:00
|
|
|
else if (!INTEL_INFO(dev)->cursor_needs_physical)
|
2014-12-01 15:40:10 -08:00
|
|
|
addr = i915_gem_obj_ggtt_offset(obj);
|
2014-12-01 15:40:12 -08:00
|
|
|
else
|
2014-12-01 15:40:10 -08:00
|
|
|
addr = obj->phys_handle->busaddr;
|
2014-09-05 17:22:31 -03:00
|
|
|
|
2014-12-01 15:40:10 -08:00
|
|
|
intel_crtc->cursor_addr = addr;
|
2016-01-07 11:54:10 +01:00
|
|
|
intel_crtc_update_cursor(crtc, state);
|
2014-09-05 17:22:31 -03:00
|
|
|
}
|
|
|
|
|
|
2014-06-10 08:28:13 -07:00
|
|
|
static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
|
|
|
|
|
int pipe)
|
|
|
|
|
{
|
|
|
|
|
struct intel_plane *cursor;
|
2015-01-21 16:35:41 -08:00
|
|
|
struct intel_plane_state *state;
|
2014-06-10 08:28:13 -07:00
|
|
|
|
|
|
|
|
cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
|
|
|
|
|
if (cursor == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2015-01-21 16:35:41 -08:00
|
|
|
state = intel_create_plane_state(&cursor->base);
|
|
|
|
|
if (!state) {
|
2014-12-23 10:41:52 -08:00
|
|
|
kfree(cursor);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-01-21 16:35:41 -08:00
|
|
|
cursor->base.state = &state->base;
|
2014-12-23 10:41:52 -08:00
|
|
|
|
2014-06-10 08:28:13 -07:00
|
|
|
cursor->can_scale = false;
|
|
|
|
|
cursor->max_downscale = 1;
|
|
|
|
|
cursor->pipe = pipe;
|
|
|
|
|
cursor->plane = pipe;
|
2015-06-24 21:59:34 +03:00
|
|
|
cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
|
2014-12-01 15:40:16 -08:00
|
|
|
cursor->check_plane = intel_check_cursor_plane;
|
2016-01-07 11:54:10 +01:00
|
|
|
cursor->update_plane = intel_update_cursor_plane;
|
2015-04-21 17:12:51 +03:00
|
|
|
cursor->disable_plane = intel_disable_cursor_plane;
|
2014-06-10 08:28:13 -07:00
|
|
|
|
|
|
|
|
drm_universal_plane_init(dev, &cursor->base, 0,
|
2015-01-21 16:35:42 -08:00
|
|
|
&intel_plane_funcs,
|
2014-06-10 08:28:13 -07:00
|
|
|
intel_cursor_formats,
|
|
|
|
|
ARRAY_SIZE(intel_cursor_formats),
|
|
|
|
|
DRM_PLANE_TYPE_CURSOR);
|
2014-10-23 07:41:34 -07:00
|
|
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
if (!dev->mode_config.rotation_property)
|
|
|
|
|
dev->mode_config.rotation_property =
|
|
|
|
|
drm_mode_create_rotation_property(dev,
|
|
|
|
|
BIT(DRM_ROTATE_0) |
|
|
|
|
|
BIT(DRM_ROTATE_180));
|
|
|
|
|
if (dev->mode_config.rotation_property)
|
|
|
|
|
drm_object_attach_property(&cursor->base.base,
|
|
|
|
|
dev->mode_config.rotation_property,
|
2015-01-21 16:35:41 -08:00
|
|
|
state->base.rotation);
|
2014-10-23 07:41:34 -07:00
|
|
|
}
|
|
|
|
|
|
2015-05-11 14:35:47 -07:00
|
|
|
if (INTEL_INFO(dev)->gen >=9)
|
|
|
|
|
state->scaler_id = -1;
|
|
|
|
|
|
2014-12-23 10:41:52 -08:00
|
|
|
drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
|
|
|
|
|
|
2014-06-10 08:28:13 -07:00
|
|
|
return &cursor->base;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-07 15:28:38 -07:00
|
|
|
static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
|
|
|
|
|
struct intel_crtc_state *crtc_state)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
struct intel_scaler *intel_scaler;
|
|
|
|
|
struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < intel_crtc->num_scalers; i++) {
|
|
|
|
|
intel_scaler = &scaler_state->scalers[i];
|
|
|
|
|
intel_scaler->in_use = 0;
|
|
|
|
|
intel_scaler->mode = PS_SCALER_MODE_DYN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scaler_state->scaler_id = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-18 21:18:47 +01: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-07 14:24:08 -08:00
|
|
|
{
|
2014-03-31 14:27:18 +03: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-07 14:24:08 -08:00
|
|
|
struct intel_crtc *intel_crtc;
|
2015-01-15 14:55:26 +02:00
|
|
|
struct intel_crtc_state *crtc_state = NULL;
|
2014-06-10 08:28:13 -07:00
|
|
|
struct drm_plane *primary = NULL;
|
|
|
|
|
struct drm_plane *cursor = NULL;
|
2014-05-29 08:06:54 -07:00
|
|
|
int i, 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-07 14:24:08 -08:00
|
|
|
|
2013-09-19 14:05:45 +02:00
|
|
|
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
|
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-07 14:24:08 -08:00
|
|
|
if (intel_crtc == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-01-15 14:55:26 +02:00
|
|
|
crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
|
|
|
|
|
if (!crtc_state)
|
|
|
|
|
goto fail;
|
2015-04-21 17:13:24 +03:00
|
|
|
intel_crtc->config = crtc_state;
|
|
|
|
|
intel_crtc->base.state = &crtc_state->base;
|
2015-02-25 11:43:26 -08:00
|
|
|
crtc_state->base.crtc = &intel_crtc->base;
|
2015-01-15 14:55:26 +02:00
|
|
|
|
2015-04-07 15:28:38 -07:00
|
|
|
/* initialize shared scalers */
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
if (pipe == PIPE_C)
|
|
|
|
|
intel_crtc->num_scalers = 1;
|
|
|
|
|
else
|
|
|
|
|
intel_crtc->num_scalers = SKL_NUM_SCALERS;
|
|
|
|
|
|
|
|
|
|
skl_init_scalers(dev, intel_crtc, crtc_state);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
primary = intel_primary_plane_create(dev, pipe);
|
2014-06-10 08:28:13 -07:00
|
|
|
if (!primary)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
cursor = intel_cursor_plane_create(dev, pipe);
|
|
|
|
|
if (!cursor)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2014-05-29 08:06:54 -07:00
|
|
|
ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
|
2014-06-10 08:28:13 -07:00
|
|
|
cursor, &intel_crtc_funcs);
|
|
|
|
|
if (ret)
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-28 17:30:01 +02:00
|
|
|
/*
|
|
|
|
|
* On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
|
2014-06-16 02:08:26 +02:00
|
|
|
* is hooked to pipe B. Hence we want plane A feeding pipe B.
|
2013-11-28 17:30:01 +02:00
|
|
|
*/
|
2009-09-10 15:28:06 -07:00
|
|
|
intel_crtc->pipe = pipe;
|
|
|
|
|
intel_crtc->plane = pipe;
|
2014-01-10 08:50:12 +01:00
|
|
|
if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) {
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
|
2010-09-13 16:53:12 +01:00
|
|
|
intel_crtc->plane = !pipe;
|
2009-09-10 15:28:06 -07:00
|
|
|
}
|
|
|
|
|
|
2014-05-30 16:35:26 +03:00
|
|
|
intel_crtc->cursor_base = ~0;
|
|
|
|
|
intel_crtc->cursor_cntl = ~0;
|
2014-08-13 11:57:05 +03:00
|
|
|
intel_crtc->cursor_size = ~0;
|
2014-04-29 13:35:46 +03:00
|
|
|
|
2015-06-24 22:00:07 +03:00
|
|
|
intel_crtc->wm.cxsr_allowed = true;
|
|
|
|
|
|
2009-12-02 13: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-07 14:24:08 -08:00
|
|
|
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
|
2014-05-15 15:33:46 +02:00
|
|
|
|
|
|
|
|
WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
|
2014-06-10 08:28:13 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
if (primary)
|
|
|
|
|
drm_plane_cleanup(primary);
|
|
|
|
|
if (cursor)
|
|
|
|
|
drm_plane_cleanup(cursor);
|
2015-01-15 14:55:26 +02:00
|
|
|
kfree(crtc_state);
|
2014-06-10 08:28:13 -07:00
|
|
|
kfree(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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2013-10-31 18:55:49 +02:00
|
|
|
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
|
|
|
|
|
{
|
|
|
|
|
struct drm_encoder *encoder = connector->base.encoder;
|
drm: Split connection_mutex out of mode_config.mutex (v3)
After the split-out of crtc locks from the big mode_config.mutex
there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID
properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other
modeset-relevant connector state (e.g. properties which control the
panel fitter).
The later is used by modeset operations. But they don't really care
about the former since it's allowed to e.g. enable a disconnected VGA
output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset
conversion Rob Clark needs to convert all modeset relevant locks into
w/w locks. This is required because the order of acquisition is
determined by how userspace supplies the atomic modeset data. This has
run into troubles in the detect path since the i915 load detect code
needs _both_ protections offered by the mode_config.mutex: It updates
probe state and it needs to change the modeset configuration to enable
the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a
plain mutex fits best, but for atomic modesets we really want a w/w
mutex. To fix this lets split out a new connection_mutex lock for the
modeset relevant parts.
For simplicity I've decided to only add one additional lock for all
connector/encoder links and modeset configuration states. We have
piles of different modeset objects in addition to those (like bridges
or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we
need to acquire this lock. Which means that fine-grained locking is
fairly irrelevant compared to the amount of time the full modeset will
take.
I've done a full audit, and there's just a few things that justify
special focus:
- Locking in drm_sysfs.c is almost completely absent. We should
sprinkle mode_config.connection_mutex over this file a bit, but
since it already lacks mode_config.mutex this patch wont make the
situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the
connector->encoder->crtc links and is called from many contexts.
Some look like they don't acquire mode_config.mutex, so this is
already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at
connector->dpms. Currently this happens without any locking, so is
already racy. I think radeon_hotplug_work_func should gain
mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already
racy.
- i915 load_detect code needs to acquire this lock. Which means the
w/w dance due to Rob's work will be nicely contained to _just_ this
function.
I've added fixme comments everywhere where it looks suspicious but in
the sysfs code. After a quick irc discussion with Dave Airlie it
sounds like the lack of locking in there is due to sysfs cleanup fun
at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to
get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
Cc: Alex Deucher <alexdeucher@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
2014-05-29 23:54:47 +02:00
|
|
|
struct drm_device *dev = connector->base.dev;
|
2013-10-31 18:55:49 +02:00
|
|
|
|
2013-11-19 12:10:12 -05:00
|
|
|
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
2013-10-31 18:55:49 +02:00
|
|
|
|
2014-11-07 11:16:01 +02:00
|
|
|
if (!encoder || WARN_ON(!encoder->crtc))
|
2013-10-31 18:55:49 +02:00
|
|
|
return INVALID_PIPE;
|
|
|
|
|
|
|
|
|
|
return to_intel_crtc(encoder->crtc)->pipe;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-29 14:43:54 -07:00
|
|
|
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
2010-11-08 19:18:58 +00:00
|
|
|
struct drm_file *file)
|
2009-04-29 14:43:54 -07:00
|
|
|
{
|
|
|
|
|
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
|
2014-07-17 23:30:04 -04:00
|
|
|
struct drm_crtc *drmmode_crtc;
|
2009-08-11 16:05:30 +02:00
|
|
|
struct intel_crtc *crtc;
|
2009-04-29 14:43:54 -07:00
|
|
|
|
2014-07-17 23:30:04 -04:00
|
|
|
drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id);
|
2009-04-29 14:43:54 -07:00
|
|
|
|
2014-07-17 23:30:04 -04:00
|
|
|
if (!drmmode_crtc) {
|
2009-04-29 14:43:54 -07:00
|
|
|
DRM_ERROR("no such CRTC id\n");
|
2013-10-17 13:35:03 +03:00
|
|
|
return -ENOENT;
|
2009-04-29 14:43:54 -07:00
|
|
|
}
|
|
|
|
|
|
2014-07-17 23:30:04 -04:00
|
|
|
crtc = to_intel_crtc(drmmode_crtc);
|
2009-08-11 16:05:30 +02:00
|
|
|
pipe_from_crtc_id->pipe = crtc->pipe;
|
2009-04-29 14:43:54 -07:00
|
|
|
|
2009-08-11 16:05:30 +02:00
|
|
|
return 0;
|
2009-04-29 14:43:54 -07:00
|
|
|
}
|
|
|
|
|
|
2012-07-12 20:08:18 +02: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-07 14:24:08 -08:00
|
|
|
{
|
2012-07-12 20:08:18 +02: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-07 14:24:08 -08:00
|
|
|
int index_mask = 0;
|
|
|
|
|
int entry = 0;
|
|
|
|
|
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, source_encoder) {
|
2014-03-03 16:15:28 +02:00
|
|
|
if (encoders_cloneable(encoder, source_encoder))
|
2012-07-12 20:08:18 +02:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
entry++;
|
|
|
|
|
}
|
2010-09-09 15:14:28 +01: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-07 14:24:08 -08:00
|
|
|
return index_mask;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-14 19:21:29 +00: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;
|
|
|
|
|
|
2014-02-07 19:12:50 +00:00
|
|
|
if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
|
2010-12-14 19:21:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 08:24:29 -07:00
|
|
|
static bool intel_crt_present(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2013-12-03 13:56:23 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9)
|
|
|
|
|
return false;
|
|
|
|
|
|
2014-10-01 20:04:15 +01:00
|
|
|
if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
|
2014-06-25 08:24:29 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (IS_CHERRYVIEW(dev))
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-12-01 23:28:55 +02:00
|
|
|
if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
|
|
|
|
|
return false;
|
|
|
|
|
|
2015-12-01 23:29:56 +02:00
|
|
|
/* DDI E can't be used if DDI A requires 4 lanes */
|
|
|
|
|
if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
|
|
|
|
|
return false;
|
|
|
|
|
|
drm/i915: Check VBT for CRT port presence on HSW/BDW
Unfortunatey there appear to quite a few HSW/BDW machines (eg.
NUCs, Brix Pro) in the wild with LPT/WPT-H that have no physical
CRT connector and non-working FDI. FDI training fails every
single time on these machines. Dunno, maybe they just didn't
bother wiring it up or something?
Unfortunately all the fuse bits and whatnot are telling us that
the CRT connector is present. And so what we get from this is tons
of false positives from the CI systems due to VGA connector forcing.
I've not found any way to detect this purely from hardware, so we
have to resort to looking at the VBT int_crt_support bit. We used
to check this bit on all platforms, but that broke all the old
machines, so the check was then restricted to VLV only in
commit 84b4e042c470 ("drm/i915: only apply crt_present check on VLV")
Considering HSW and VLV VBT probably got defined around the same time,
it should be reasonably safe to assume that the bits is sane for
HSW/BDW as well. At least I have one copy of some VBT spec here that
says it's meant for both VLV and HSW, and it knows about the bit
(lists it being valid from version 155 onwards). Also I have two
desktop machines with actual CRT ports and both have
int_crt_support==1 in their VBTs.
Also we already trust VBT >= 155 to tell us various details about
the DDI ports, so trusting it a bit more seems reasonable.
As far as VLV goes, the added VBT version check should be fine. Even
if someone has some weird VLV machine with a very old VBT version,
it just means they'll end up with a shadow CRT connector. IIRC the
reason for eliminating the shadow CRT connector on VLV was to speed
up display probing rather than fixing something more serious.
v2: Move the platform checks into the VBT parsing code
Also check that the VBT version is at least 155
v3: Improve commit message (Paulo)
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1449005493-15487-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-01 23:31:33 +02:00
|
|
|
if (!dev_priv->vbt.int_crt_support)
|
2014-06-25 08:24:29 -07:00
|
|
|
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-07 14:24:08 -08:00
|
|
|
static void intel_setup_outputs(struct drm_device *dev)
|
|
|
|
|
{
|
2009-01-22 13:01:02 -08:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-09-09 15:14:28 +01:00
|
|
|
struct intel_encoder *encoder;
|
2010-07-16 14:46:29 -04:00
|
|
|
bool dpd_is_edp = 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-07 14:24:08 -08:00
|
|
|
|
2013-06-06 22:22:47 +02:00
|
|
|
intel_lvds_init(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-07 14:24:08 -08:00
|
|
|
|
2014-06-25 08:24:29 -07:00
|
|
|
if (intel_crt_present(dev))
|
2012-11-20 13:27:40 -02:00
|
|
|
intel_crt_init(dev);
|
2010-07-16 14:46:29 -04:00
|
|
|
|
2014-08-19 12:05:01 +05:30
|
|
|
if (IS_BROXTON(dev)) {
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: Broxton doesn't support port detection via the
|
|
|
|
|
* DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
|
|
|
|
|
* detect the ports.
|
|
|
|
|
*/
|
|
|
|
|
intel_ddi_init(dev, PORT_A);
|
|
|
|
|
intel_ddi_init(dev, PORT_B);
|
|
|
|
|
intel_ddi_init(dev, PORT_C);
|
|
|
|
|
} else if (HAS_DDI(dev)) {
|
2012-05-09 15:37:27 -03:00
|
|
|
int found;
|
|
|
|
|
|
2015-03-06 15:53:32 -08:00
|
|
|
/*
|
|
|
|
|
* Haswell uses DDI functions to detect digital outputs.
|
|
|
|
|
* On SKL pre-D0 the strap isn't connected, so we assume
|
|
|
|
|
* it's there.
|
|
|
|
|
*/
|
2015-09-18 20:03:35 +03:00
|
|
|
found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
|
2015-03-06 15:53:32 -08:00
|
|
|
/* WaIgnoreDDIAStrap: skl */
|
2015-10-28 04:16:45 -07:00
|
|
|
if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
2012-05-09 15:37:27 -03:00
|
|
|
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);
|
2015-08-07 17:35:21 -07:00
|
|
|
/*
|
|
|
|
|
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
|
|
|
|
|
*/
|
2015-10-28 04:16:45 -07:00
|
|
|
if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
|
2015-08-07 17:35:21 -07:00
|
|
|
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
|
|
|
|
|
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
|
|
|
|
|
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
|
|
|
|
|
intel_ddi_init(dev, PORT_E);
|
|
|
|
|
|
2012-05-09 15:37:27 -03:00
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
2010-07-16 14:46:29 -04:00
|
|
|
int found;
|
2013-11-01 18:22:39 +02:00
|
|
|
dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
|
2012-10-27 15:52:05 +02:00
|
|
|
|
|
|
|
|
if (has_edp_a(dev))
|
|
|
|
|
intel_dp_init(dev, DP_A, PORT_A);
|
2010-07-16 14:46:29 -04:00
|
|
|
|
2013-02-19 16:21:46 -03:00
|
|
|
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
|
2010-03-30 15:11:33 +08:00
|
|
|
/* PCH SDVOB multiplex with HDMIB */
|
2015-11-06 21:29:59 +02:00
|
|
|
found = intel_sdvo_init(dev, PCH_SDVOB, PORT_B);
|
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-18 19:00:27 -03: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-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, PCH_DP_B, PORT_B);
|
2009-06-05 15:38:43 +08:00
|
|
|
}
|
|
|
|
|
|
2013-02-19 16:21:46 -03: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-18 19:00:27 -03:00
|
|
|
intel_hdmi_init(dev, PCH_HDMIC, PORT_C);
|
2009-06-05 15:38:43 +08:00
|
|
|
|
2013-02-19 16:21:46 -03: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-18 19:00:27 -03: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-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, PCH_DP_C, PORT_C);
|
2009-07-24 01:00:31 +08:00
|
|
|
|
2012-10-27 15:52:05 +02:00
|
|
|
if (I915_READ(PCH_DP_D) & DP_DETECTED)
|
2012-07-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, PCH_DP_D, PORT_D);
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2014-10-09 19:37:15 +03:00
|
|
|
/*
|
|
|
|
|
* The DP_DETECTED bit is the latched state of the DDC
|
|
|
|
|
* SDA pin at boot. However since eDP doesn't require DDC
|
|
|
|
|
* (no way to plug in a DP->HDMI dongle) the DDC pins for
|
|
|
|
|
* eDP ports may have been muxed to an alternate function.
|
|
|
|
|
* Thus we can't rely on the DP_DETECTED bit alone to detect
|
|
|
|
|
* eDP ports. Consult the VBT as well as DP_DETECTED to
|
|
|
|
|
* detect eDP ports.
|
|
|
|
|
*/
|
2015-09-18 20:03:34 +03:00
|
|
|
if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
|
2015-01-09 14:21:14 +02:00
|
|
|
!intel_dp_is_edp(dev, PORT_B))
|
2015-09-18 20:03:34 +03:00
|
|
|
intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
|
|
|
|
|
if (I915_READ(VLV_DP_B) & DP_DETECTED ||
|
2014-10-09 19:37:15 +03:00
|
|
|
intel_dp_is_edp(dev, PORT_B))
|
2015-09-18 20:03:34 +03:00
|
|
|
intel_dp_init(dev, VLV_DP_B, PORT_B);
|
drm/i915: preserve dispaly init order on ByT
This patch changes HDMI port registration order for the BayTrail platform.
The story is that in kernel version 3.11 i915 supported only one HDMI port -
the HDMIB port. So this port ended up being HDMI-1 in user-space.
But commit '6f6005a drm/i915: expose HDMI connectors on port C on BYT'
introduced HDMIC port support. And added HDMIC registration prior to HDMIB,
so HDMIB became HDMI-2 and HDMIC became HDMI-1.
Well, this is fine as far as the kernel is concerned. i915 does not give any
guarantees to the numbering, and has never given them.
However, this breaks wayland setup in Tizen IVI. We have only one single HDMI
port on our hardware, and it is connected to HDMIB. Our configuration relies on
the fact that it is HDMI-1.
Well, certainly this is user-space problem which was exposed with Jesse's
patch. However, there is a reason why we have to do this assumption - we use
touchscreen monitors and we have to associate event devices with the monitors,
and this is not easy to do dynamically, so we just have a static setup.
Anyway, while the user-space setup will have to be fixed regardless, let's
chane the HDMI port registration order so that HDMIB stays HDMI-1, just like it
was in 3.11. Simply because there is no strong reason for changing the order in
the kernel, and it'll help setups like ours in sense that we'll have more time
for fixing the issue properly.
Also amend the commentary which looks a bit out-of-date.
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
[danvet: Drop the commment, SDVOC is gone and we have a proper HDMIC
define now.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-10-16 18:10:41 +03:00
|
|
|
|
2015-09-18 20:03:34 +03:00
|
|
|
if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
|
2015-01-09 14:21:14 +02:00
|
|
|
!intel_dp_is_edp(dev, PORT_C))
|
2015-09-18 20:03:34 +03:00
|
|
|
intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
|
|
|
|
|
if (I915_READ(VLV_DP_C) & DP_DETECTED ||
|
2014-10-09 19:37:15 +03:00
|
|
|
intel_dp_is_edp(dev, PORT_C))
|
2015-09-18 20:03:34 +03:00
|
|
|
intel_dp_init(dev, VLV_DP_C, PORT_C);
|
2012-09-27 19:13:07 +05:30
|
|
|
|
2014-04-09 13:28:56 +03:00
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
2014-10-09 19:37:15 +03:00
|
|
|
/* eDP not supported on port D, so don't check VBT */
|
2015-09-18 20:03:34 +03:00
|
|
|
if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
|
|
|
|
|
intel_hdmi_init(dev, CHV_HDMID, PORT_D);
|
|
|
|
|
if (I915_READ(CHV_DP_D) & DP_DETECTED)
|
|
|
|
|
intel_dp_init(dev, CHV_DP_D, PORT_D);
|
2014-04-09 13:28:56 +03:00
|
|
|
}
|
|
|
|
|
|
2013-08-27 15:12:26 +03:00
|
|
|
intel_dsi_init(dev);
|
2015-07-07 11:44:32 +02:00
|
|
|
} else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
|
2009-08-24 13:50:23 +08:00
|
|
|
bool found = false;
|
2009-01-02 13: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-18 19:00:27 -03:00
|
|
|
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
|
2009-12-11 11:07:17 -08:00
|
|
|
DRM_DEBUG_KMS("probing SDVOB\n");
|
2015-11-06 21:29:59 +02:00
|
|
|
found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
|
2015-07-07 09:10:07 +02:00
|
|
|
if (!found && IS_G4X(dev)) {
|
2009-12-11 11:07:17 -08:00
|
|
|
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-18 19:00:27 -03:00
|
|
|
intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
|
2009-12-11 11:07:17 -08:00
|
|
|
}
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2015-07-07 09:10:07 +02:00
|
|
|
if (!found && IS_G4X(dev))
|
2012-07-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, DP_B, PORT_B);
|
2009-01-22 13:01:02 -08:00
|
|
|
}
|
2009-03-13 15:42:14 -04: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-18 19:00:27 -03:00
|
|
|
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
|
2009-12-11 11:07:17 -08:00
|
|
|
DRM_DEBUG_KMS("probing SDVOC\n");
|
2015-11-06 21:29:59 +02:00
|
|
|
found = intel_sdvo_init(dev, GEN3_SDVOC, PORT_C);
|
2009-12-11 11: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-18 19:00:27 -03:00
|
|
|
if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2015-07-07 09:10:07 +02:00
|
|
|
if (IS_G4X(dev)) {
|
2009-12-11 11:07:17 -08:00
|
|
|
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-18 19:00:27 -03:00
|
|
|
intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
|
2009-12-11 11:07:17 -08:00
|
|
|
}
|
2015-07-07 09:10:07 +02:00
|
|
|
if (IS_G4X(dev))
|
2012-07-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, DP_C, PORT_C);
|
2009-01-22 13:01:02 -08:00
|
|
|
}
|
2009-08-24 13:50:23 +08:00
|
|
|
|
2015-07-07 09:10:07 +02:00
|
|
|
if (IS_G4X(dev) &&
|
2013-05-08 13:14:08 +03:00
|
|
|
(I915_READ(DP_D) & DP_DETECTED))
|
2012-07-17 17:53:45 -03:00
|
|
|
intel_dp_init(dev, DP_D, PORT_D);
|
2009-10-22 16:11:14 -07: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-07 14: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-07 14:24:08 -08:00
|
|
|
intel_tv_init(dev);
|
|
|
|
|
|
2014-11-14 08:52:28 -08:00
|
|
|
intel_psr_init(dev);
|
2014-06-13 05:10:03 -07:00
|
|
|
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
2010-09-09 15:14:28 +01:00
|
|
|
encoder->base.possible_crtcs = encoder->crtc_mask;
|
|
|
|
|
encoder->base.possible_clones =
|
2012-07-12 20:08:18 +02: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-07 14:24:08 -08:00
|
|
|
}
|
2011-01-11 17:06:04 +00:00
|
|
|
|
2012-12-01 12:04:25 -02:00
|
|
|
intel_init_pch_refclk(dev);
|
2012-10-27 15:52:05 +02: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
|
|
|
|
{
|
2014-06-13 11:10:53 +03:00
|
|
|
struct drm_device *dev = fb->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-07 14:24:08 -08:00
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
|
|
|
|
2014-02-10 18:00:38 +01:00
|
|
|
drm_framebuffer_cleanup(fb);
|
2014-06-13 11:10:53 +03:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
2014-02-10 18:00:38 +01:00
|
|
|
WARN_ON(!intel_fb->obj->framebuffer_references--);
|
2014-06-13 11:10:53 +03:00
|
|
|
drm_gem_object_unreference(&intel_fb->obj->base);
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
kfree(intel_fb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
|
2010-11-08 19:18:58 +00: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-07 14:24:08 -08:00
|
|
|
unsigned int *handle)
|
|
|
|
|
{
|
|
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
2010-11-08 19:18:58 +00: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-07 14:24:08 -08:00
|
|
|
|
2015-10-13 14:22:26 +01:00
|
|
|
if (obj->userptr.mm) {
|
|
|
|
|
DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-08 19:18:58 +00: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-07-08 16:22:45 -07:00
|
|
|
static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
|
|
|
|
|
struct drm_file *file,
|
|
|
|
|
unsigned flags, unsigned color,
|
|
|
|
|
struct drm_clip_rect *clips,
|
|
|
|
|
unsigned num_clips)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = fb->dev;
|
|
|
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
|
|
|
struct drm_i915_gem_object *obj = intel_fb->obj;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
2015-07-14 16:29:14 -03:00
|
|
|
intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
|
2015-07-08 16:22:45 -07:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
|
|
|
|
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-07 14: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,
|
2015-07-08 16:22:45 -07:00
|
|
|
.dirty = intel_user_framebuffer_dirty,
|
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-07 14:24:08 -08:00
|
|
|
};
|
|
|
|
|
|
2015-02-27 11:15:18 +00:00
|
|
|
static
|
|
|
|
|
u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
|
|
|
|
|
uint32_t pixel_format)
|
|
|
|
|
{
|
|
|
|
|
u32 gen = INTEL_INFO(dev)->gen;
|
|
|
|
|
|
|
|
|
|
if (gen >= 9) {
|
|
|
|
|
/* "The stride in bytes must not exceed the of the size of 8K
|
|
|
|
|
* pixels and 32K bytes."
|
|
|
|
|
*/
|
|
|
|
|
return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
2015-02-27 11:15:18 +00:00
|
|
|
return 32*1024;
|
|
|
|
|
} else if (gen >= 4) {
|
|
|
|
|
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
|
|
|
|
|
return 16*1024;
|
|
|
|
|
else
|
|
|
|
|
return 32*1024;
|
|
|
|
|
} else if (gen >= 3) {
|
|
|
|
|
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
|
|
|
|
|
return 8*1024;
|
|
|
|
|
else
|
|
|
|
|
return 16*1024;
|
|
|
|
|
} else {
|
|
|
|
|
/* XXX DSPC is limited to 4k tiled */
|
|
|
|
|
return 8*1024;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-02 21:18:00 +01:00
|
|
|
static int intel_framebuffer_init(struct drm_device *dev,
|
|
|
|
|
struct intel_framebuffer *intel_fb,
|
|
|
|
|
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
{
|
2015-03-23 11:10:32 +00:00
|
|
|
unsigned int aligned_height;
|
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-07 14:24:08 -08:00
|
|
|
int ret;
|
2015-02-27 11:15:18 +00:00
|
|
|
u32 pitch_limit, stride_alignment;
|
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-07 14:24:08 -08:00
|
|
|
|
2013-10-09 21:23:51 +02:00
|
|
|
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
|
|
|
|
2015-02-10 17:16:06 +00:00
|
|
|
if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
|
|
|
|
|
/* Enforce that fb modifier and tiling mode match, but only for
|
|
|
|
|
* X-tiled. This is needed for FBC. */
|
|
|
|
|
if (!!(obj->tiling_mode == I915_TILING_X) !=
|
|
|
|
|
!!(mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)) {
|
|
|
|
|
DRM_DEBUG("tiling_mode doesn't match fb modifier\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (obj->tiling_mode == I915_TILING_X)
|
|
|
|
|
mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
|
|
|
|
else if (obj->tiling_mode == I915_TILING_Y) {
|
|
|
|
|
DRM_DEBUG("No Y tiling for legacy addfb\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 11:15:24 +00:00
|
|
|
/* Passed in modifier sanity checking. */
|
|
|
|
|
switch (mode_cmd->modifier[0]) {
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED:
|
|
|
|
|
case I915_FORMAT_MOD_Yf_TILED:
|
|
|
|
|
if (INTEL_INFO(dev)->gen < 9) {
|
|
|
|
|
DRM_DEBUG("Unsupported tiling 0x%llx!\n",
|
|
|
|
|
mode_cmd->modifier[0]);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
case DRM_FORMAT_MOD_NONE:
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2015-03-23 12:43:50 -07:00
|
|
|
DRM_DEBUG("Unsupported fb modifier 0x%llx!\n",
|
|
|
|
|
mode_cmd->modifier[0]);
|
2010-08-08 12:34:44 +01:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2010-08-08 12:34:44 +01:00
|
|
|
|
2015-02-27 11:15:18 +00:00
|
|
|
stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
|
|
|
|
|
mode_cmd->pixel_format);
|
|
|
|
|
if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
|
|
|
|
|
DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
|
|
|
|
|
mode_cmd->pitches[0], stride_alignment);
|
2010-08-08 12:34:44 +01:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2010-08-08 12:34:44 +01:00
|
|
|
|
2015-02-27 11:15:18 +00:00
|
|
|
pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
|
|
|
|
|
mode_cmd->pixel_format);
|
2013-06-25 17:26:45 +01:00
|
|
|
if (mode_cmd->pitches[0] > pitch_limit) {
|
2015-02-27 11:15:18 +00:00
|
|
|
DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
|
|
|
|
|
mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ?
|
2015-02-10 17:16:06 +00:00
|
|
|
"tiled" : "linear",
|
2013-06-25 17:26:45 +01:00
|
|
|
mode_cmd->pitches[0], pitch_limit);
|
2012-10-31 17:50:18 +02:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2012-10-31 17:50:18 +02:00
|
|
|
|
2015-02-10 17:16:06 +00:00
|
|
|
if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED &&
|
2012-12-18 22:13:14 +00: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 17:50:18 +02:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2012-10-31 17:50:18 +02:00
|
|
|
|
2012-10-31 17:50:14 +02:00
|
|
|
/* Reject formats not supported by any plane early. */
|
2011-11-14 14:51:28 -08:00
|
|
|
switch (mode_cmd->pixel_format) {
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_C8:
|
2011-11-17 18:05:13 +02:00
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
2012-10-31 17:50:14 +02:00
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XRGB1555:
|
2012-12-18 22:13:14 +00:00
|
|
|
if (INTEL_INFO(dev)->gen > 3) {
|
2013-06-07 15:43:05 +00:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
2012-10-31 17:50:14 +02:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2012-10-31 17:50:14 +02:00
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
|
|
|
|
INTEL_INFO(dev)->gen < 9) {
|
2015-05-19 12:29:16 +01:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
2011-11-17 18:05:13 +02:00
|
|
|
case DRM_FORMAT_XRGB2101010:
|
2012-10-31 17:50:14 +02:00
|
|
|
case DRM_FORMAT_XBGR2101010:
|
2012-12-18 22:13:14 +00:00
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
2013-06-07 15:43:05 +00:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
2012-10-31 17:50:14 +02:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2011-06-24 12:19:27 -07:00
|
|
|
break;
|
2015-05-15 19:06:01 +01:00
|
|
|
case DRM_FORMAT_ABGR2101010:
|
2015-12-09 12:29:35 -08:00
|
|
|
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
2015-05-15 19:06:01 +01:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-11-17 18:05:13 +02:00
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
|
|
case DRM_FORMAT_UYVY:
|
|
|
|
|
case DRM_FORMAT_YVYU:
|
|
|
|
|
case DRM_FORMAT_VYUY:
|
2012-12-18 22:13:14 +00:00
|
|
|
if (INTEL_INFO(dev)->gen < 5) {
|
2013-06-07 15:43:05 +00:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
2012-10-31 17:50:14 +02:00
|
|
|
return -EINVAL;
|
2012-12-18 22:13:14 +00:00
|
|
|
}
|
2010-08-08 12:34:44 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2013-06-07 15:43:05 +00:00
|
|
|
DRM_DEBUG("unsupported pixel format: %s\n",
|
|
|
|
|
drm_get_format_name(mode_cmd->pixel_format));
|
2010-08-08 12:34:44 +01:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-31 17:50:19 +02:00
|
|
|
/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
|
|
|
|
|
if (mode_cmd->offsets[0] != 0)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
2015-01-20 12:51:45 +00:00
|
|
|
aligned_height = intel_fb_align_height(dev, mode_cmd->height,
|
2015-02-10 17:16:10 +00:00
|
|
|
mode_cmd->pixel_format,
|
|
|
|
|
mode_cmd->modifier[0]);
|
2013-10-09 21:55:33 +02:00
|
|
|
/* FIXME drm helper for size checks (especially planar formats)? */
|
|
|
|
|
if (obj->base.size < aligned_height * mode_cmd->pitches[0])
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
2012-12-13 23:38:38 +01:00
|
|
|
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
|
|
|
|
|
intel_fb->obj = obj;
|
2013-10-09 21:23:52 +02:00
|
|
|
intel_fb->obj->framebuffer_references++;
|
2012-12-13 23:38:38 +01: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-07 14: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,
|
2015-11-11 19:11:29 +02:00
|
|
|
const struct drm_mode_fb_cmd2 *user_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-07 14:24:08 -08:00
|
|
|
{
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
struct drm_framebuffer *fb;
|
2010-11-08 19:18:58 +00:00
|
|
|
struct drm_i915_gem_object *obj;
|
drm/i915: Don't clobber the addfb2 ioctl params
We try to convert the old way of of specifying fb tiling (obj->tiling)
into the new fb modifiers. We store the result in the passed in mode_cmd
structure. But that structure comes directly from the addfb2 ioctl, and
gets copied back out to userspace, which means we're clobbering the
modifiers that the user provided (all 0 since the DRM_MODE_FB_MODIFIERS
flag wasn't even set by the user). Hence if the user reuses the struct
for another addfb2, the ioctl will be rejected since it's now asking for
some modifiers w/o the flag set.
Fix the problem by making a copy of the user provided structure. We can
play any games we want with the copy.
IGT-Version: 1.12-git (x86_64) (Linux: 4.4.0-rc1-stereo+ x86_64)
...
Subtest basic-X-tiled: SUCCESS (0.001s)
Test assertion failure function pitch_tests, file kms_addfb_basic.c:167:
Failed assertion: drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0
Last errno: 22, Invalid argument
Stack trace:
#0 [__igt_fail_assert+0x101]
#1 [pitch_tests+0x619]
#2 [__real_main426+0x2f]
#3 [main+0x23]
#4 [__libc_start_main+0xf0]
#5 [_start+0x29]
#6 [<unknown>+0x29]
Subtest framebuffer-vs-set-tiling failed.
**** DEBUG ****
Test assertion failure function pitch_tests, file kms_addfb_basic.c:167:
Failed assertion: drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0
Last errno: 22, Invalid argument
**** END ****
Subtest framebuffer-vs-set-tiling: FAIL (0.003s)
...
IGT-Version: 1.12-git (x86_64) (Linux: 4.4.0-rc1-stereo+ x86_64)
Subtest framebuffer-vs-set-tiling: SUCCESS (0.000s)
Cc: stable@vger.kernel.org # v4.1+
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Fixes: 2a80eada326f ("drm/i915: Add fb format modifier support")
Testcase: igt/kms_addfb_basic/clobbered-modifier
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1447261890-3960-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-11 19:11:28 +02:00
|
|
|
struct drm_mode_fb_cmd2 mode_cmd = *user_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-07 14:24:08 -08:00
|
|
|
|
2011-11-14 14:51:28 -08:00
|
|
|
obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
|
drm/i915: Don't clobber the addfb2 ioctl params
We try to convert the old way of of specifying fb tiling (obj->tiling)
into the new fb modifiers. We store the result in the passed in mode_cmd
structure. But that structure comes directly from the addfb2 ioctl, and
gets copied back out to userspace, which means we're clobbering the
modifiers that the user provided (all 0 since the DRM_MODE_FB_MODIFIERS
flag wasn't even set by the user). Hence if the user reuses the struct
for another addfb2, the ioctl will be rejected since it's now asking for
some modifiers w/o the flag set.
Fix the problem by making a copy of the user provided structure. We can
play any games we want with the copy.
IGT-Version: 1.12-git (x86_64) (Linux: 4.4.0-rc1-stereo+ x86_64)
...
Subtest basic-X-tiled: SUCCESS (0.001s)
Test assertion failure function pitch_tests, file kms_addfb_basic.c:167:
Failed assertion: drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0
Last errno: 22, Invalid argument
Stack trace:
#0 [__igt_fail_assert+0x101]
#1 [pitch_tests+0x619]
#2 [__real_main426+0x2f]
#3 [main+0x23]
#4 [__libc_start_main+0xf0]
#5 [_start+0x29]
#6 [<unknown>+0x29]
Subtest framebuffer-vs-set-tiling failed.
**** DEBUG ****
Test assertion failure function pitch_tests, file kms_addfb_basic.c:167:
Failed assertion: drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0
Last errno: 22, Invalid argument
**** END ****
Subtest framebuffer-vs-set-tiling: FAIL (0.003s)
...
IGT-Version: 1.12-git (x86_64) (Linux: 4.4.0-rc1-stereo+ x86_64)
Subtest framebuffer-vs-set-tiling: SUCCESS (0.000s)
Cc: stable@vger.kernel.org # v4.1+
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Fixes: 2a80eada326f ("drm/i915: Add fb format modifier support")
Testcase: igt/kms_addfb_basic/clobbered-modifier
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1447261890-3960-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-11 19:11:28 +02:00
|
|
|
mode_cmd.handles[0]));
|
2011-02-19 11:31:06 +00:00
|
|
|
if (&obj->base == NULL)
|
2010-08-08 13:36:38 +01: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-07 14:24:08 -08:00
|
|
|
|
2015-11-23 09:04:05 +01:00
|
|
|
fb = intel_framebuffer_create(dev, &mode_cmd, obj);
|
drm/i915: On fb alloc failure, unref gem object where it gets refed
Currently when allocating a framebuffer fails, the gem object gets
unrefed at the bottom of the call stack in __intel_framebuffer_create,
not where it gets refed, which is in intel_framebuffer_create_for_mode
(via i915_gem_alloc_object) and in intel_user_framebuffer_create
(via drm_gem_object_lookup).
This invites mistakes: __intel_framebuffer_create is also called from
intelfb_alloc, and as discovered by Tvrtko Ursulin, a double unref
was introduced there with a8bb6818270c ("drm/i915: Fix error path leak
in fbdev fb allocation").
As suggested by Ville Syrjälä, fix the double unref and improve code
clarity by moving the unref away from __intel_framebuffer_create to
where the gem object gets refed.
Based on Tvrtko Ursulin's original v2.
v3: On fb alloc failure, unref gem object where it gets refed,
fix double unref in separate commit (Ville Syrjälä)
v4: Lock struct_mutex on unref (Chris Wilson)
v5: Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC,
rephrase commit message (Jani Nicula)
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
[MBP 5,3 2009 nvidia MCP79 + G96 pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina]
Fixes: a8bb6818270c ("drm/i915: Fix error path leak in fbdev fb
allocation")
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/2161c5062ef5d6458f8ae14d924a26d4d1dba317.1446892879.git.lukas@wunner.de
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-04 11:50:58 +02:00
|
|
|
if (IS_ERR(fb))
|
|
|
|
|
drm_gem_object_unreference_unlocked(&obj->base);
|
|
|
|
|
|
|
|
|
|
return 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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-08-10 13:34:08 +02:00
|
|
|
#ifndef CONFIG_DRM_FBDEV_EMULATION
|
2013-10-08 17:44:49 +02:00
|
|
|
static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
|
2013-10-09 09:18:51 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
static const struct drm_mode_config_funcs intel_mode_funcs = {
|
|
|
|
|
.fb_create = intel_user_framebuffer_create,
|
2013-10-08 17:44:49 +02:00
|
|
|
.output_poll_changed = intel_fbdev_output_poll_changed,
|
2015-01-21 16:35:44 -08:00
|
|
|
.atomic_check = intel_atomic_check,
|
|
|
|
|
.atomic_commit = intel_atomic_commit,
|
2015-06-04 10:21:28 +02:00
|
|
|
.atomic_state_alloc = intel_atomic_state_alloc,
|
|
|
|
|
.atomic_state_clear = intel_atomic_state_clear,
|
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-07 14:24:08 -08:00
|
|
|
};
|
|
|
|
|
|
2009-09-21 10:42:27 -07: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;
|
|
|
|
|
|
2013-06-03 22:40:22 +02:00
|
|
|
if (HAS_PCH_SPLIT(dev) || IS_G4X(dev))
|
|
|
|
|
dev_priv->display.find_dpll = g4x_find_best_dpll;
|
2014-04-09 13:28:18 +03:00
|
|
|
else if (IS_CHERRYVIEW(dev))
|
|
|
|
|
dev_priv->display.find_dpll = chv_find_best_dpll;
|
2013-06-03 22:40:22 +02:00
|
|
|
else if (IS_VALLEYVIEW(dev))
|
|
|
|
|
dev_priv->display.find_dpll = vlv_find_best_dpll;
|
|
|
|
|
else if (IS_PINEVIEW(dev))
|
|
|
|
|
dev_priv->display.find_dpll = pnv_find_best_dpll;
|
|
|
|
|
else
|
|
|
|
|
dev_priv->display.find_dpll = i9xx_find_best_dpll;
|
|
|
|
|
|
2015-01-20 12:51:51 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 9) {
|
|
|
|
|
dev_priv->display.get_pipe_config = haswell_get_pipe_config;
|
2015-01-20 12:51:52 +00:00
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
|
|
skylake_get_initial_plane_config;
|
2015-01-20 12:51:51 +00:00
|
|
|
dev_priv->display.crtc_compute_clock =
|
|
|
|
|
haswell_crtc_compute_clock;
|
|
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
|
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
|
|
skylake_update_primary_plane;
|
|
|
|
|
} else if (HAS_DDI(dev)) {
|
2013-03-28 10:42:00 +01:00
|
|
|
dev_priv->display.get_pipe_config = haswell_get_pipe_config;
|
2015-01-20 12:51:52 +00:00
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
|
|
ironlake_get_initial_plane_config;
|
2014-10-29 11:32:34 +02:00
|
|
|
dev_priv->display.crtc_compute_clock =
|
|
|
|
|
haswell_crtc_compute_clock;
|
2012-10-23 18:29:51 -02:00
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
2015-01-20 12:51:51 +00:00
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
|
|
ironlake_update_primary_plane;
|
2012-10-05 12:05:55 -03:00
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
2013-03-28 10:42:00 +01:00
|
|
|
dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
|
2015-01-20 12:51:52 +00:00
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
|
|
ironlake_get_initial_plane_config;
|
2014-10-29 11:32:35 +02:00
|
|
|
dev_priv->display.crtc_compute_clock =
|
|
|
|
|
ironlake_crtc_compute_clock;
|
2012-06-29 22:39:33 +02:00
|
|
|
dev_priv->display.crtc_enable = ironlake_crtc_enable;
|
|
|
|
|
dev_priv->display.crtc_disable = ironlake_crtc_disable;
|
2014-03-18 17:22:55 -07:00
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
|
|
ironlake_update_primary_plane;
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2013-04-18 14:51:36 -07:00
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
2015-01-20 12:51:52 +00:00
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
|
|
i9xx_get_initial_plane_config;
|
2014-10-29 11:32:36 +02:00
|
|
|
dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
|
2013-04-18 14:51:36 -07:00
|
|
|
dev_priv->display.crtc_enable = valleyview_crtc_enable;
|
|
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
2014-03-18 17:22:55 -07:00
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
|
|
i9xx_update_primary_plane;
|
2011-03-30 13:01:02 -07:00
|
|
|
} else {
|
2013-03-28 10:42:00 +01:00
|
|
|
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
2015-01-20 12:51:52 +00:00
|
|
|
dev_priv->display.get_initial_plane_config =
|
|
|
|
|
i9xx_get_initial_plane_config;
|
2014-10-29 11:32:36 +02:00
|
|
|
dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
|
2012-06-29 22:39:33 +02:00
|
|
|
dev_priv->display.crtc_enable = i9xx_crtc_enable;
|
|
|
|
|
dev_priv->display.crtc_disable = i9xx_crtc_disable;
|
2014-03-18 17:22:55 -07:00
|
|
|
dev_priv->display.update_primary_plane =
|
|
|
|
|
i9xx_update_primary_plane;
|
2011-03-30 13:01:02 -07:00
|
|
|
}
|
2009-09-21 10:42:27 -07:00
|
|
|
|
|
|
|
|
/* Returns the core display clock speed */
|
2015-10-28 04:16:45 -07:00
|
|
|
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
2015-03-31 14:12:01 +03:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
skylake_get_display_clock_speed;
|
2015-06-23 14:14:26 -07:00
|
|
|
else if (IS_BROXTON(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
broxton_get_display_clock_speed;
|
2015-03-31 14:12:01 +03:00
|
|
|
else if (IS_BROADWELL(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
broadwell_get_display_clock_speed;
|
|
|
|
|
else if (IS_HASWELL(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
haswell_get_display_clock_speed;
|
2015-12-09 12:29:35 -08:00
|
|
|
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
2012-03-28 13:39:23 -07:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
valleyview_get_display_clock_speed;
|
2015-03-31 14:11:54 +03:00
|
|
|
else if (IS_GEN5(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
ilk_get_display_clock_speed;
|
2015-03-31 14:11:56 +03:00
|
|
|
else if (IS_I945G(dev) || IS_BROADWATER(dev) ||
|
2015-05-22 11:22:33 +03:00
|
|
|
IS_GEN6(dev) || IS_IVYBRIDGE(dev))
|
2009-09-21 10:42:27 -07:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
i945_get_display_clock_speed;
|
2015-05-22 11:22:33 +03:00
|
|
|
else if (IS_GM45(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
gm45_get_display_clock_speed;
|
|
|
|
|
else if (IS_CRESTLINE(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
i965gm_get_display_clock_speed;
|
|
|
|
|
else if (IS_PINEVIEW(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
pnv_get_display_clock_speed;
|
|
|
|
|
else if (IS_G33(dev) || IS_G4X(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
g33_get_display_clock_speed;
|
2009-09-21 10:42:27 -07:00
|
|
|
else if (IS_I915G(dev))
|
|
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
i915_get_display_clock_speed;
|
2013-07-26 08:35:42 +02:00
|
|
|
else if (IS_I945GM(dev) || IS_845G(dev))
|
2009-09-21 10:42:27 -07: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-15 22:57:33 +02:00
|
|
|
else if (IS_I85X(dev))
|
2009-09-21 10:42:27 -07:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
2015-05-22 11:22:31 +03:00
|
|
|
i85x_get_display_clock_speed;
|
2015-05-22 11:22:34 +03:00
|
|
|
else { /* 830 */
|
|
|
|
|
WARN(!IS_I830(dev), "Unknown platform. Assuming 133 MHz CDCLK\n");
|
2009-09-21 10:42:27 -07:00
|
|
|
dev_priv->display.get_display_clock_speed =
|
|
|
|
|
i830_get_display_clock_speed;
|
2015-05-22 11:22:34 +03:00
|
|
|
}
|
2009-09-21 10:42:27 -07:00
|
|
|
|
2014-10-27 16:26:43 +02:00
|
|
|
if (IS_GEN5(dev)) {
|
2014-08-11 09:06:39 +05:30
|
|
|
dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
|
|
|
|
|
} else if (IS_GEN6(dev)) {
|
|
|
|
|
dev_priv->display.fdi_link_train = gen6_fdi_link_train;
|
|
|
|
|
} else if (IS_IVYBRIDGE(dev)) {
|
|
|
|
|
/* FIXME: detect B0+ stepping and use auto training */
|
|
|
|
|
dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
|
2014-09-02 16:53:57 -03:00
|
|
|
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
2014-08-11 09:06:39 +05:30
|
|
|
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
|
2015-06-15 12:33:56 +02:00
|
|
|
if (IS_BROADWELL(dev)) {
|
|
|
|
|
dev_priv->display.modeset_commit_cdclk =
|
|
|
|
|
broadwell_modeset_commit_cdclk;
|
|
|
|
|
dev_priv->display.modeset_calc_cdclk =
|
|
|
|
|
broadwell_modeset_calc_cdclk;
|
|
|
|
|
}
|
2015-12-09 12:29:35 -08:00
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
2015-06-15 12:33:56 +02:00
|
|
|
dev_priv->display.modeset_commit_cdclk =
|
|
|
|
|
valleyview_modeset_commit_cdclk;
|
|
|
|
|
dev_priv->display.modeset_calc_cdclk =
|
|
|
|
|
valleyview_modeset_calc_cdclk;
|
2014-11-24 13:37:39 +05:30
|
|
|
} else if (IS_BROXTON(dev)) {
|
2015-06-15 12:33:56 +02:00
|
|
|
dev_priv->display.modeset_commit_cdclk =
|
|
|
|
|
broxton_modeset_commit_cdclk;
|
|
|
|
|
dev_priv->display.modeset_calc_cdclk =
|
|
|
|
|
broxton_modeset_calc_cdclk;
|
2009-09-21 10:42:27 -07:00
|
|
|
}
|
2011-06-16 09:19:13 -07:00
|
|
|
|
|
|
|
|
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-16 12:18:54 -07:00
|
|
|
case 7:
|
2013-11-02 21:07:07 -07:00
|
|
|
case 8: /* FIXME(BDW): Check that the gen8 RCS flip works. */
|
2011-06-16 12:18:54 -07:00
|
|
|
dev_priv->display.queue_flip = intel_gen7_queue_flip;
|
|
|
|
|
break;
|
2014-11-13 17:51:46 +00:00
|
|
|
case 9:
|
2015-02-10 17:16:12 +00:00
|
|
|
/* Drop through - unsupported since execlist only. */
|
|
|
|
|
default:
|
|
|
|
|
/* Default just returns -ENODEV to indicate unsupported */
|
|
|
|
|
dev_priv->display.queue_flip = intel_default_queue_flip;
|
2011-06-16 09:19:13 -07:00
|
|
|
}
|
2013-11-08 16:48:56 +02:00
|
|
|
|
2014-09-04 14:53:14 +03:00
|
|
|
mutex_init(&dev_priv->pps_mutex);
|
2009-09-21 10:42:27 -07:00
|
|
|
}
|
|
|
|
|
|
2010-07-19 13:53:12 -07: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-16 15:34:10 -04:00
|
|
|
static void quirk_pipea_force(struct drm_device *dev)
|
2010-07-19 13:53:12 -07:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
dev_priv->quirks |= QUIRK_PIPEA_FORCE;
|
2012-04-01 13:16:49 +02:00
|
|
|
DRM_INFO("applying pipe a force quirk\n");
|
2010-07-19 13:53:12 -07:00
|
|
|
}
|
|
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
static void quirk_pipeb_force(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
|
|
dev_priv->quirks |= QUIRK_PIPEB_FORCE;
|
|
|
|
|
DRM_INFO("applying pipe b force quirk\n");
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-12 14:56:22 -07: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 13:16:49 +02:00
|
|
|
DRM_INFO("applying lvds SSC disable quirk\n");
|
2011-07-12 14:56:22 -07:00
|
|
|
}
|
|
|
|
|
|
2012-03-15 15:56:26 +01:00
|
|
|
/*
|
2012-03-15 15:56:27 +01:00
|
|
|
* A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight
|
|
|
|
|
* brightness value
|
2012-03-15 15:56:26 +01: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 13:16:49 +02:00
|
|
|
DRM_INFO("applying inverted panel brightness quirk\n");
|
2011-07-12 14:56:22 -07:00
|
|
|
}
|
|
|
|
|
|
2014-07-03 23:27:50 +00:00
|
|
|
/* Some VBT's incorrectly indicate no backlight is present */
|
|
|
|
|
static void quirk_backlight_present(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
dev_priv->quirks |= QUIRK_BACKLIGHT_PRESENT;
|
|
|
|
|
DRM_INFO("applying backlight present quirk\n");
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-19 13:53:12 -07:00
|
|
|
struct intel_quirk {
|
|
|
|
|
int device;
|
|
|
|
|
int subsystem_vendor;
|
|
|
|
|
int subsystem_device;
|
|
|
|
|
void (*hook)(struct drm_device *dev);
|
|
|
|
|
};
|
|
|
|
|
|
2012-10-14 15:46:38 +02: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-16 14:07:40 -07:00
|
|
|
static struct intel_quirk intel_quirks[] = {
|
2010-07-19 13:53:12 -07: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 },
|
|
|
|
|
|
2014-08-15 01:22:06 +03:00
|
|
|
/* 830 needs to leave pipe A & dpll A up */
|
|
|
|
|
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
|
|
|
|
|
|
2014-08-15 01:22:07 +03:00
|
|
|
/* 830 needs to leave pipe B & dpll B up */
|
|
|
|
|
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipeb_force },
|
|
|
|
|
|
2011-07-12 14:56:22 -07:00
|
|
|
/* Lenovo U160 cannot use SSC on LVDS */
|
|
|
|
|
{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
|
2011-07-28 18:52:06 +02:00
|
|
|
|
|
|
|
|
/* Sony Vaio Y cannot use SSC on LVDS */
|
|
|
|
|
{ 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
|
2012-03-15 15:56:27 +01:00
|
|
|
|
2013-12-28 21:00:39 +01:00
|
|
|
/* Acer Aspire 5734Z must invert backlight brightness */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
|
|
|
|
|
|
|
|
|
|
/* Acer/eMachines G725 */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
|
|
|
|
|
|
|
|
|
|
/* Acer/eMachines e725 */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
|
|
|
|
|
|
|
|
|
|
/* Acer/Packard Bell NCL20 */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
|
|
|
|
|
|
|
|
|
|
/* Acer Aspire 4736Z */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
|
2014-01-13 17:30:34 +02:00
|
|
|
|
|
|
|
|
/* Acer Aspire 5336 */
|
|
|
|
|
{ 0x2a42, 0x1025, 0x048a, quirk_invert_brightness },
|
2014-07-03 23:27:51 +00:00
|
|
|
|
|
|
|
|
/* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
|
|
|
|
|
{ 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
|
2014-07-03 23:27:52 +00:00
|
|
|
|
2014-08-21 16:08:02 +00:00
|
|
|
/* Acer C720 Chromebook (Core i3 4005U) */
|
|
|
|
|
{ 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
|
|
|
|
|
|
2014-10-28 20:25:53 +01:00
|
|
|
/* Apple Macbook 2,1 (Core 2 T7400) */
|
|
|
|
|
{ 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
|
|
|
|
|
|
2015-11-05 11:49:59 +02:00
|
|
|
/* Apple Macbook 4,1 */
|
|
|
|
|
{ 0x2a02, 0x106b, 0x00a1, quirk_backlight_present },
|
|
|
|
|
|
2014-07-03 23:27:52 +00:00
|
|
|
/* Toshiba CB35 Chromebook (Celeron 2955U) */
|
|
|
|
|
{ 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
|
2014-07-11 22:16:30 +00:00
|
|
|
|
|
|
|
|
/* HP Chromebook 14 (Celeron 2955U) */
|
|
|
|
|
{ 0x0a06, 0x103c, 0x21ed, quirk_backlight_present },
|
2015-02-19 10:53:39 +02:00
|
|
|
|
|
|
|
|
/* Dell Chromebook 11 */
|
|
|
|
|
{ 0x0a06, 0x1028, 0x0a35, quirk_backlight_present },
|
2015-10-30 14:50:24 +02:00
|
|
|
|
|
|
|
|
/* Dell Chromebook 11 (2015 version) */
|
|
|
|
|
{ 0x0a16, 0x1028, 0x0a35, quirk_backlight_present },
|
2010-07-19 13:53:12 -07: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 15:46:38 +02: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-19 13:53:12 -07:00
|
|
|
}
|
|
|
|
|
|
2010-08-13 15:11:26 -07: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
|
2010-08-13 15:11:26 -07:00
|
|
|
|
2014-01-22 21:32:38 +02:00
|
|
|
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
|
2010-08-13 15:11:26 -07:00
|
|
|
vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
|
2012-04-06 11:46:27 -07:00
|
|
|
outb(SR01, VGA_SR_INDEX);
|
2010-08-13 15:11:26 -07:00
|
|
|
sr1 = inb(VGA_SR_DATA);
|
|
|
|
|
outb(sr1 | 1<<5, VGA_SR_DATA);
|
|
|
|
|
vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
|
|
|
|
|
udelay(300);
|
|
|
|
|
|
2014-12-16 18:38:37 +02:00
|
|
|
I915_WRITE(vga_reg, VGA_DISP_DISABLE);
|
2010-08-13 15:11:26 -07:00
|
|
|
POSTING_READ(vga_reg);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-10 15:50:11 +02:00
|
|
|
void intel_modeset_init_hw(struct drm_device *dev)
|
|
|
|
|
{
|
2015-12-03 14:31:06 +01:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2015-06-03 15:45:07 +03:00
|
|
|
intel_update_cdclk(dev);
|
2015-12-03 14:31:06 +01:00
|
|
|
|
|
|
|
|
dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
|
|
|
|
|
|
2012-06-28 15:55:35 -03:00
|
|
|
intel_prepare_ddi(dev);
|
2012-04-10 15:50:11 +02:00
|
|
|
intel_init_clock_gating(dev);
|
2012-06-24 16:42:32 +02:00
|
|
|
intel_enable_gt_powersave(dev);
|
2012-04-10 15:50:11 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-03 11:37:41 -08:00
|
|
|
/*
|
|
|
|
|
* Calculate what we think the watermarks should be for the state we've read
|
|
|
|
|
* out of the hardware and then immediately program those watermarks so that
|
|
|
|
|
* we ensure the hardware settings match our internal state.
|
|
|
|
|
*
|
|
|
|
|
* We can calculate what we think WM's should be by creating a duplicate of the
|
|
|
|
|
* current state (which was constructed during hardware readout) and running it
|
|
|
|
|
* through the atomic check code to calculate new watermark values in the
|
|
|
|
|
* state object.
|
|
|
|
|
*/
|
|
|
|
|
static void sanitize_watermarks(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
|
|
struct drm_atomic_state *state;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
struct drm_crtc_state *cstate;
|
|
|
|
|
struct drm_modeset_acquire_ctx ctx;
|
|
|
|
|
int ret;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Only supported on platforms that use atomic watermark design */
|
2016-01-06 11:34:30 -08:00
|
|
|
if (!dev_priv->display.optimize_watermarks)
|
2015-12-03 11:37:41 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We need to hold connection_mutex before calling duplicate_state so
|
|
|
|
|
* that the connector loop is protected.
|
|
|
|
|
*/
|
|
|
|
|
drm_modeset_acquire_init(&ctx, 0);
|
|
|
|
|
retry:
|
|
|
|
|
ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
|
|
|
|
|
if (ret == -EDEADLK) {
|
|
|
|
|
drm_modeset_backoff(&ctx);
|
|
|
|
|
goto retry;
|
|
|
|
|
} else if (WARN_ON(ret)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state = drm_atomic_helper_duplicate_state(dev, &ctx);
|
|
|
|
|
if (WARN_ON(IS_ERR(state)))
|
|
|
|
|
return;
|
|
|
|
|
|
2016-01-06 11:34:30 -08:00
|
|
|
/*
|
|
|
|
|
* Hardware readout is the only time we don't want to calculate
|
|
|
|
|
* intermediate watermarks (since we don't trust the current
|
|
|
|
|
* watermarks).
|
|
|
|
|
*/
|
|
|
|
|
to_intel_atomic_state(state)->skip_intermediate_wm = true;
|
|
|
|
|
|
2015-12-03 11:37:41 -08:00
|
|
|
ret = intel_atomic_check(dev, state);
|
|
|
|
|
if (ret) {
|
|
|
|
|
/*
|
|
|
|
|
* If we fail here, it means that the hardware appears to be
|
|
|
|
|
* programmed in a way that shouldn't be possible, given our
|
|
|
|
|
* understanding of watermark requirements. This might mean a
|
|
|
|
|
* mistake in the hardware readout code or a mistake in the
|
|
|
|
|
* watermark calculations for a given platform. Raise a WARN
|
|
|
|
|
* so that this is noticeable.
|
|
|
|
|
*
|
|
|
|
|
* If this actually happens, we'll have to just leave the
|
|
|
|
|
* BIOS-programmed watermarks untouched and hope for the best.
|
|
|
|
|
*/
|
|
|
|
|
WARN(true, "Could not determine valid watermarks for inherited state\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write calculated watermark values back */
|
|
|
|
|
to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config;
|
|
|
|
|
for_each_crtc_in_state(state, crtc, cstate, i) {
|
|
|
|
|
struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
|
|
|
|
|
|
2016-01-06 11:34:30 -08:00
|
|
|
cs->wm.need_postvbl_update = true;
|
|
|
|
|
dev_priv->display.optimize_watermarks(cs);
|
2015-12-03 11:37:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
drm_atomic_state_free(state);
|
|
|
|
|
drm_modeset_drop_locks(&ctx);
|
|
|
|
|
drm_modeset_acquire_fini(&ctx);
|
|
|
|
|
}
|
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
void intel_modeset_init(struct drm_device *dev)
|
|
|
|
|
{
|
2009-08-17 13:31:43 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2014-03-03 17:31:47 +00:00
|
|
|
int sprite, ret;
|
2014-03-03 17:31:44 +00:00
|
|
|
enum pipe pipe;
|
2014-03-07 08:57:48 -08:00
|
|
|
struct intel_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-07 14:24:08 -08:00
|
|
|
|
|
|
|
|
drm_mode_config_init(dev);
|
|
|
|
|
|
|
|
|
|
dev->mode_config.min_width = 0;
|
|
|
|
|
dev->mode_config.min_height = 0;
|
|
|
|
|
|
2011-09-29 16:20:42 +01:00
|
|
|
dev->mode_config.preferred_depth = 24;
|
|
|
|
|
dev->mode_config.prefer_shadow = 1;
|
|
|
|
|
|
2015-02-10 17:16:16 +00:00
|
|
|
dev->mode_config.allow_fb_modifiers = true;
|
|
|
|
|
|
2012-05-17 13:27:23 +02: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-07 14:24:08 -08:00
|
|
|
|
2010-07-19 13:53:12 -07:00
|
|
|
intel_init_quirks(dev);
|
|
|
|
|
|
2012-04-18 15:29:26 -03:00
|
|
|
intel_init_pm(dev);
|
|
|
|
|
|
2013-04-05 13:12:39 -07:00
|
|
|
if (INTEL_INFO(dev)->num_pipes == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
drm/i915: Preserve SSC earlier
Commit 92122789b2d6 ("drm/i915: preserve SSC if previously set v3")
added code to intel_modeset_gem_init to override the SSC status read
from VBT with the SSC status set by BIOS.
However, intel_modeset_gem_init is invoked *after* intel_modeset_init,
which calls intel_setup_outputs, which *modifies* SSC status by way of
intel_init_pch_refclk. So unlike advertised, intel_modeset_gem_init
doesn't preserve the SSC status set by BIOS but whatever
intel_init_pch_refclk decided on.
This is a problem on dual gpu laptops such as the MacBook Pro which
require either a handler to switch DDC lines, or the discrete gpu
to proxy DDC/AUX communication: Both the handler and the discrete
gpu may initialize after the i915 driver, and consequently, an LVDS
connector may initially seem disconnected and the SSC therefore
is disabled by intel_init_pch_refclk, but on reprobe the connector
may turn out to be connected and the SSC must then be enabled.
Due to 92122789b2d6 however, the SSC is not enabled on reprobe since
it is assumed BIOS disabled it while in fact it was disabled by
intel_init_pch_refclk.
Also, because the SSC status is preserved so late, the preserved value
only ever gets used on resume but not on panel initialization:
intel_modeset_init calls intel_init_display which indirectly calls
intel_panel_use_ssc via multiple subroutines, *before* the BIOS value
overrides the VBT value in intel_modeset_gem_init (intel_panel_use_ssc
is the sole user of dev_priv->vbt.lvds_use_ssc).
Fix this by moving the code introduced by 92122789b2d6 from
intel_modeset_gem_init to intel_modeset_init before the invocation
of intel_setup_outputs and intel_init_display.
Add a DRM_DEBUG_KMS as suggested way back by Jani:
http://lists.freedesktop.org/archives/intel-gfx/2014-June/046666.html
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina -- work in progress]
Fixes: 92122789b2d6 ("drm/i915: preserve SSC if previously set v3")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-07-15 13:57:35 +02:00
|
|
|
/*
|
|
|
|
|
* There may be no VBT; and if the BIOS enabled SSC we can
|
|
|
|
|
* just keep using it to avoid unnecessary flicker. Whereas if the
|
|
|
|
|
* BIOS isn't using it, don't assume it will work even if the VBT
|
|
|
|
|
* indicates as much.
|
|
|
|
|
*/
|
|
|
|
|
if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
|
|
|
|
bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
|
|
|
|
|
DREF_SSC1_ENABLE);
|
|
|
|
|
|
|
|
|
|
if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
|
|
|
|
|
DRM_DEBUG_KMS("SSC %sabled by BIOS, overriding VBT which says %sabled\n",
|
|
|
|
|
bios_lvds_use_ssc ? "en" : "dis",
|
|
|
|
|
dev_priv->vbt.lvds_use_ssc ? "en" : "dis");
|
|
|
|
|
dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-21 10:42:27 -07:00
|
|
|
intel_init_display(dev);
|
2014-10-27 16:26:43 +02:00
|
|
|
intel_init_audio(dev);
|
2009-09-21 10:42:27 -07:00
|
|
|
|
2010-09-17 00:32:17 +01:00
|
|
|
if (IS_GEN2(dev)) {
|
|
|
|
|
dev->mode_config.max_width = 2048;
|
|
|
|
|
dev->mode_config.max_height = 2048;
|
|
|
|
|
} else if (IS_GEN3(dev)) {
|
2009-07-12 23:53:17 -07: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-07 14:24:08 -08:00
|
|
|
} else {
|
2010-09-17 00:32:17 +01: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-07 14:24:08 -08:00
|
|
|
}
|
2014-03-28 14:17:49 +00:00
|
|
|
|
2014-08-13 11:57:05 +03:00
|
|
|
if (IS_845G(dev) || IS_I865G(dev)) {
|
|
|
|
|
dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512;
|
|
|
|
|
dev->mode_config.cursor_height = 1023;
|
|
|
|
|
} else if (IS_GEN2(dev)) {
|
2014-03-28 14:17:49 +00:00
|
|
|
dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
|
|
|
|
|
dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
|
|
|
|
|
} else {
|
|
|
|
|
dev->mode_config.cursor_width = MAX_CURSOR_WIDTH;
|
|
|
|
|
dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-17 12: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-07 14:24:08 -08:00
|
|
|
|
2009-10-09 11:39:41 +08:00
|
|
|
DRM_DEBUG_KMS("%d display pipe%s available.\n",
|
2013-03-13 14:05:41 -07: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-07 14:24:08 -08:00
|
|
|
|
2014-08-18 13:49:10 +01:00
|
|
|
for_each_pipe(dev_priv, pipe) {
|
2014-03-03 17:31:44 +00:00
|
|
|
intel_crtc_init(dev, pipe);
|
2015-02-28 14:54:09 +00:00
|
|
|
for_each_sprite(dev_priv, pipe, sprite) {
|
2014-03-03 17:31:47 +00:00
|
|
|
ret = intel_plane_init(dev, pipe, sprite);
|
2013-04-02 11:22:20 -07:00
|
|
|
if (ret)
|
2013-04-17 17:48:51 +03:00
|
|
|
DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
|
2014-03-03 17:31:47 +00:00
|
|
|
pipe_name(pipe), sprite_name(pipe, sprite), ret);
|
2013-04-02 11:22:20 -07: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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2015-09-24 23:29:18 +03:00
|
|
|
intel_update_czclk(dev_priv);
|
|
|
|
|
intel_update_cdclk(dev);
|
|
|
|
|
|
2013-06-05 13:34:06 +02:00
|
|
|
intel_shared_dpll_init(dev);
|
2012-04-20 17:11:53 +01:00
|
|
|
|
2010-08-13 15:11:26 -07: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-07 14:24:08 -08:00
|
|
|
intel_setup_outputs(dev);
|
2012-11-15 11:32:20 +00:00
|
|
|
|
drm: Split connection_mutex out of mode_config.mutex (v3)
After the split-out of crtc locks from the big mode_config.mutex
there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID
properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other
modeset-relevant connector state (e.g. properties which control the
panel fitter).
The later is used by modeset operations. But they don't really care
about the former since it's allowed to e.g. enable a disconnected VGA
output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset
conversion Rob Clark needs to convert all modeset relevant locks into
w/w locks. This is required because the order of acquisition is
determined by how userspace supplies the atomic modeset data. This has
run into troubles in the detect path since the i915 load detect code
needs _both_ protections offered by the mode_config.mutex: It updates
probe state and it needs to change the modeset configuration to enable
the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a
plain mutex fits best, but for atomic modesets we really want a w/w
mutex. To fix this lets split out a new connection_mutex lock for the
modeset relevant parts.
For simplicity I've decided to only add one additional lock for all
connector/encoder links and modeset configuration states. We have
piles of different modeset objects in addition to those (like bridges
or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we
need to acquire this lock. Which means that fine-grained locking is
fairly irrelevant compared to the amount of time the full modeset will
take.
I've done a full audit, and there's just a few things that justify
special focus:
- Locking in drm_sysfs.c is almost completely absent. We should
sprinkle mode_config.connection_mutex over this file a bit, but
since it already lacks mode_config.mutex this patch wont make the
situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the
connector->encoder->crtc links and is called from many contexts.
Some look like they don't acquire mode_config.mutex, so this is
already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at
connector->dpms. Currently this happens without any locking, so is
already racy. I think radeon_hotplug_work_func should gain
mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already
racy.
- i915 load_detect code needs to acquire this lock. Which means the
w/w dance due to Rob's work will be nicely contained to _just_ this
function.
I've added fixme comments everywhere where it looks suspicious but in
the sysfs code. After a quick irc discussion with Dave Airlie it
sounds like the lack of locking in there is due to sysfs cleanup fun
at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to
get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
Cc: Alex Deucher <alexdeucher@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
2014-05-29 23:54:47 +02:00
|
|
|
drm_modeset_lock_all(dev);
|
2015-07-13 16:30:25 +02:00
|
|
|
intel_modeset_setup_hw_state(dev);
|
drm: Split connection_mutex out of mode_config.mutex (v3)
After the split-out of crtc locks from the big mode_config.mutex
there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID
properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other
modeset-relevant connector state (e.g. properties which control the
panel fitter).
The later is used by modeset operations. But they don't really care
about the former since it's allowed to e.g. enable a disconnected VGA
output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset
conversion Rob Clark needs to convert all modeset relevant locks into
w/w locks. This is required because the order of acquisition is
determined by how userspace supplies the atomic modeset data. This has
run into troubles in the detect path since the i915 load detect code
needs _both_ protections offered by the mode_config.mutex: It updates
probe state and it needs to change the modeset configuration to enable
the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a
plain mutex fits best, but for atomic modesets we really want a w/w
mutex. To fix this lets split out a new connection_mutex lock for the
modeset relevant parts.
For simplicity I've decided to only add one additional lock for all
connector/encoder links and modeset configuration states. We have
piles of different modeset objects in addition to those (like bridges
or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we
need to acquire this lock. Which means that fine-grained locking is
fairly irrelevant compared to the amount of time the full modeset will
take.
I've done a full audit, and there's just a few things that justify
special focus:
- Locking in drm_sysfs.c is almost completely absent. We should
sprinkle mode_config.connection_mutex over this file a bit, but
since it already lacks mode_config.mutex this patch wont make the
situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the
connector->encoder->crtc links and is called from many contexts.
Some look like they don't acquire mode_config.mutex, so this is
already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at
connector->dpms. Currently this happens without any locking, so is
already racy. I think radeon_hotplug_work_func should gain
mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already
racy.
- i915 load_detect code needs to acquire this lock. Which means the
w/w dance due to Rob's work will be nicely contained to _just_ this
function.
I've added fixme comments everywhere where it looks suspicious but in
the sysfs code. After a quick irc discussion with Dave Airlie it
sounds like the lack of locking in there is due to sysfs cleanup fun
at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to
get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
Cc: Alex Deucher <alexdeucher@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
2014-05-29 23:54:47 +02:00
|
|
|
drm_modeset_unlock_all(dev);
|
2014-03-07 08:57:48 -08:00
|
|
|
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2015-07-14 12:33:29 +02:00
|
|
|
struct intel_initial_plane_config plane_config = {};
|
|
|
|
|
|
2014-03-07 08:57:48 -08:00
|
|
|
if (!crtc->active)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Note that reserving the BIOS fb up front prevents us
|
|
|
|
|
* from stuffing other stolen allocations like the ring
|
|
|
|
|
* on top. This prevents some ugliness at boot time, and
|
|
|
|
|
* can even allow for smooth boot transitions if the BIOS
|
|
|
|
|
* fb is large enough for the active pipe configuration.
|
|
|
|
|
*/
|
2015-07-14 12:33:29 +02:00
|
|
|
dev_priv->display.get_initial_plane_config(crtc,
|
|
|
|
|
&plane_config);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the fb is shared between multiple heads, we'll
|
|
|
|
|
* just get the first one.
|
|
|
|
|
*/
|
|
|
|
|
intel_find_initial_plane_obj(crtc, &plane_config);
|
2014-03-07 08:57:48 -08:00
|
|
|
}
|
2015-12-03 11:37:41 -08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure hardware watermarks really match the state we read out.
|
|
|
|
|
* Note that we need to do this after reconstructing the BIOS fb's
|
|
|
|
|
* since the watermark calculation done here will use pstate->fb.
|
|
|
|
|
*/
|
|
|
|
|
sanitize_watermarks(dev);
|
2011-03-29 10:40:27 +01:00
|
|
|
}
|
|
|
|
|
|
2012-07-04 17:51:47 +02: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;
|
2014-08-11 13:15:35 +03:00
|
|
|
struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
|
2012-07-04 17:51:47 +02:00
|
|
|
|
|
|
|
|
/* 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. */
|
2015-03-03 15:21:56 +02:00
|
|
|
for_each_intel_connector(dev, connector) {
|
2012-07-04 17:51:47 +02:00
|
|
|
if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
|
|
|
|
|
crt = &connector->base;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!crt)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-08-11 13:15:35 +03:00
|
|
|
if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
|
2015-03-20 16:18:02 +02:00
|
|
|
intel_release_load_detect_pipe(crt, &load_detect_temp, ctx);
|
2012-07-04 17:51:47 +02:00
|
|
|
}
|
|
|
|
|
|
2012-10-10 23:14:00 +02:00
|
|
|
static bool
|
|
|
|
|
intel_check_plane_mapping(struct intel_crtc *crtc)
|
|
|
|
|
{
|
2013-03-13 14:05:41 -07:00
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-09-22 19:50:01 +03:00
|
|
|
u32 val;
|
2012-10-10 23:14:00 +02:00
|
|
|
|
2013-03-13 14:05:41 -07:00
|
|
|
if (INTEL_INFO(dev)->num_pipes == 1)
|
2012-10-10 23:14:00 +02:00
|
|
|
return true;
|
|
|
|
|
|
2015-09-22 19:50:01 +03:00
|
|
|
val = I915_READ(DSPCNTR(!crtc->plane));
|
2012-10-10 23:14:00 +02:00
|
|
|
|
|
|
|
|
if ((val & DISPLAY_PLANE_ENABLE) &&
|
|
|
|
|
(!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-26 19:39:19 +03:00
|
|
|
static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
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-02 20:28:59 +02: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;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t 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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* Clear any frame start delays used for debugging left by the BIOS */
|
|
|
|
|
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
|
|
|
|
|
|
2014-05-20 17:20:05 +03:00
|
|
|
/* restore vblank interrupts to correct state */
|
2015-02-13 21:03:42 +01:00
|
|
|
drm_crtc_vblank_reset(&crtc->base);
|
2014-08-06 14:50:01 +03:00
|
|
|
if (crtc->active) {
|
2015-09-10 18:59:08 +03:00
|
|
|
struct intel_plane *plane;
|
|
|
|
|
|
2015-02-13 21:03:42 +01:00
|
|
|
drm_crtc_vblank_on(&crtc->base);
|
2015-09-10 18:59:08 +03:00
|
|
|
|
|
|
|
|
/* Disable everything but the primary plane */
|
|
|
|
|
for_each_intel_plane_on_crtc(dev, crtc, plane) {
|
|
|
|
|
if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
plane->disable_plane(&plane->base, &crtc->base);
|
|
|
|
|
}
|
2015-02-13 21:03:42 +01:00
|
|
|
}
|
2014-05-20 17:20:05 +03: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-02 20:28:59 +02:00
|
|
|
/* We need to sanitize the plane -> pipe mapping first because this will
|
2012-10-10 23:14:00 +02: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-02 20:28:59 +02:00
|
|
|
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;
|
2015-04-21 17:12:53 +03:00
|
|
|
to_intel_plane_state(crtc->base.primary->state)->visible = 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-02 20:28:59 +02:00
|
|
|
crtc->plane = !plane;
|
2015-06-12 11:15:39 +02:00
|
|
|
intel_crtc_disable_noatomic(&crtc->base);
|
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-02 20:28:59 +02:00
|
|
|
crtc->plane = plane;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 17:51:47 +02: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-02 20:28:59 +02:00
|
|
|
/* Adjust the state of the output pipe according to whether we
|
|
|
|
|
* have active connectors/encoders. */
|
2015-08-26 19:39:19 +03:00
|
|
|
if (!intel_crtc_has_encoders(crtc))
|
2015-06-12 11:15:39 +02:00
|
|
|
intel_crtc_disable_noatomic(&crtc->base);
|
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-02 20:28:59 +02:00
|
|
|
|
2015-06-01 12:49:52 +02:00
|
|
|
if (crtc->active != crtc->base.state->active) {
|
2015-08-26 19:39:19 +03:00
|
|
|
struct intel_encoder *encoder;
|
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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* This can happen either due to bugs in the get_hw_state
|
2015-06-12 11:15:39 +02:00
|
|
|
* functions or because of calls to intel_crtc_disable_noatomic,
|
|
|
|
|
* or because the pipe is force-enabled due to the
|
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-02 20:28:59 +02:00
|
|
|
* pipe A quirk. */
|
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
|
|
|
|
|
crtc->base.base.id,
|
2015-02-25 13:12:16 -08:00
|
|
|
crtc->base.state->enable ? "enabled" : "disabled",
|
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-02 20:28:59 +02:00
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
|
|
|
2015-07-14 13:45:32 +02:00
|
|
|
WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
|
2015-05-11 10:45:15 +02:00
|
|
|
crtc->base.state->active = crtc->active;
|
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-02 20:28:59 +02:00
|
|
|
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);
|
|
|
|
|
|
2015-08-05 12:37:09 +02:00
|
|
|
for_each_encoder_on_crtc(dev, &crtc->base, encoder)
|
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-02 20:28:59 +02:00
|
|
|
encoder->base.crtc = NULL;
|
|
|
|
|
}
|
2014-05-14 15:40:34 +02:00
|
|
|
|
2014-09-03 14:09:52 +03:00
|
|
|
if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
|
2014-03-24 00:01:41 +01:00
|
|
|
/*
|
|
|
|
|
* We start out with underrun reporting disabled to avoid races.
|
|
|
|
|
* For correct bookkeeping mark this on active crtcs.
|
|
|
|
|
*
|
2014-05-14 15:40:34 +02:00
|
|
|
* Also on gmch platforms we dont have any hardware bits to
|
|
|
|
|
* disable the underrun reporting. Which means we need to start
|
|
|
|
|
* out with underrun reporting disabled also on inactive pipes,
|
|
|
|
|
* since otherwise we'll complain about the garbage we read when
|
|
|
|
|
* e.g. coming up after runtime pm.
|
|
|
|
|
*
|
2014-03-24 00:01:41 +01:00
|
|
|
* No protection against concurrent access is required - at
|
|
|
|
|
* worst a fifo underrun happens which also sets this to false.
|
|
|
|
|
*/
|
|
|
|
|
crtc->cpu_fifo_underrun_disabled = true;
|
|
|
|
|
crtc->pch_fifo_underrun_disabled = 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-02 20:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
|
|
|
|
{
|
|
|
|
|
struct intel_connector *connector;
|
|
|
|
|
struct drm_device *dev = encoder->base.dev;
|
2015-08-05 12:37:07 +02:00
|
|
|
bool active = false;
|
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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
2015-08-05 12:37:07 +02:00
|
|
|
for_each_intel_connector(dev, connector) {
|
|
|
|
|
if (connector->base.encoder != &encoder->base)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
active = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (active && !has_active_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-02 20:28:59 +02:00
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
|
|
|
|
|
encoder->base.base.id,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.name);
|
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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* 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,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.name);
|
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-02 20:28:59 +02:00
|
|
|
encoder->disable(encoder);
|
2014-06-28 02:04:01 +03:00
|
|
|
if (encoder->post_disable)
|
|
|
|
|
encoder->post_disable(encoder);
|
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-02 20:28:59 +02:00
|
|
|
}
|
2014-04-25 10:56:22 +02:00
|
|
|
encoder->base.crtc = NULL;
|
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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* 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. */
|
2015-03-03 15:21:56 +02:00
|
|
|
for_each_intel_connector(dev, connector) {
|
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-02 20:28:59 +02:00
|
|
|
if (connector->encoder != encoder)
|
|
|
|
|
continue;
|
2014-04-25 10:56:22 +02:00
|
|
|
connector->base.dpms = DRM_MODE_DPMS_OFF;
|
|
|
|
|
connector->base.encoder = NULL;
|
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-02 20:28:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Enabled encoders without active connectors will be fixed in
|
|
|
|
|
* the crtc fixup. */
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-18 00:02:16 +02:00
|
|
|
void i915_redisable_vga_power_on(struct drm_device *dev)
|
2012-12-19 11:03:41 +01:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
drm/i915: Type safe register read/write
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.
This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.
The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.
As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
lea 0x70024(%rdx,%rax,1),%r9d
mov $0x1,%edx
- movslq %r9d,%r9
- mov %r9,%rsi
- mov %r9,-0x58(%rbp)
- callq *0xd8(%rbx)
+ mov %r9d,%esi
+ mov %r9d,-0x48(%rbp)
callq *0xd8(%rbx)
So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.
v2: i915_mmio_reg_{offset,equal,valid}() helpers added
s/_REG/_MMIO/ in the register defines
mo more switch statements left to worry about
ring_emit stuff got sorted in a prep patch
cmd parser, lrc context and w/a batch buildup also in prep patch
vgpu stuff cleaned up and moved to a prep patch
all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-11-18 15:33:26 +02:00
|
|
|
i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
|
2012-12-19 11:03:41 +01:00
|
|
|
|
2014-02-18 00:02:16 +02:00
|
|
|
if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
|
|
|
|
|
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
|
|
|
|
|
i915_disable_vga(dev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void i915_redisable_vga(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
2013-08-02 16:22:24 -03:00
|
|
|
/* This function can be called both from intel_modeset_setup_hw_state or
|
|
|
|
|
* at a very early point in our resume sequence, where the power well
|
|
|
|
|
* structures are not yet restored. Since this function is at a very
|
|
|
|
|
* paranoid "someone might have enabled VGA while we were not looking"
|
|
|
|
|
* level, just check if the power well is enabled instead of trying to
|
|
|
|
|
* follow the "don't touch the power well if we don't need it" policy
|
|
|
|
|
* the rest of the driver uses. */
|
2014-09-30 10:56:39 +02:00
|
|
|
if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA))
|
2013-08-02 16:22:24 -03:00
|
|
|
return;
|
|
|
|
|
|
2014-02-18 00:02:16 +02:00
|
|
|
i915_redisable_vga_power_on(dev);
|
2012-12-19 11:03:41 +01:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 18:59:08 +03:00
|
|
|
static bool primary_get_hw_state(struct intel_plane *plane)
|
2014-04-30 17:43:01 +03:00
|
|
|
{
|
2015-09-10 18:59:08 +03:00
|
|
|
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
2014-04-30 17:43:01 +03:00
|
|
|
|
2015-09-10 18:59:08 +03:00
|
|
|
return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
|
2015-06-15 12:33:51 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 18:59:08 +03:00
|
|
|
/* FIXME read out full plane state for all planes */
|
|
|
|
|
static void readout_plane_state(struct intel_crtc *crtc)
|
2015-06-15 12:33:51 +02:00
|
|
|
{
|
2015-09-23 16:11:41 +02:00
|
|
|
struct drm_plane *primary = crtc->base.primary;
|
2015-09-10 18:59:08 +03:00
|
|
|
struct intel_plane_state *plane_state =
|
2015-09-23 16:11:41 +02:00
|
|
|
to_intel_plane_state(primary->state);
|
2015-06-15 12:33:51 +02:00
|
|
|
|
2015-09-24 15:53:17 -07:00
|
|
|
plane_state->visible = crtc->active &&
|
2015-09-23 16:11:41 +02:00
|
|
|
primary_get_hw_state(to_intel_plane(primary));
|
|
|
|
|
|
|
|
|
|
if (plane_state->visible)
|
|
|
|
|
crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
|
2014-04-30 17:43:01 +03:00
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:17 +02:00
|
|
|
static void intel_modeset_readout_hw_state(struct drm_device *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-02 20:28:59 +02:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
enum pipe pipe;
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
struct intel_encoder *encoder;
|
|
|
|
|
struct intel_connector *connector;
|
2013-06-05 13:34:16 +02:00
|
|
|
int i;
|
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-02 20:28:59 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
dev_priv->active_crtcs = 0;
|
|
|
|
|
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2015-12-10 12:33:57 +01:00
|
|
|
struct intel_crtc_state *crtc_state = crtc->config;
|
|
|
|
|
int pixclk = 0;
|
2013-04-17 20:15:07 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
__drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
|
|
|
|
|
memset(crtc_state, 0, sizeof(*crtc_state));
|
|
|
|
|
crtc_state->base.crtc = &crtc->base;
|
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-02 20:28:59 +02:00
|
|
|
|
2015-12-10 12:33:57 +01:00
|
|
|
crtc_state->base.active = crtc_state->base.enable =
|
|
|
|
|
dev_priv->display.get_pipe_config(crtc, crtc_state);
|
|
|
|
|
|
|
|
|
|
crtc->base.enabled = crtc_state->base.enable;
|
|
|
|
|
crtc->active = crtc_state->base.active;
|
|
|
|
|
|
|
|
|
|
if (crtc_state->base.active) {
|
|
|
|
|
dev_priv->active_crtcs |= 1 << crtc->pipe;
|
|
|
|
|
|
|
|
|
|
if (IS_BROADWELL(dev_priv)) {
|
|
|
|
|
pixclk = ilk_pipe_pixel_rate(crtc_state);
|
|
|
|
|
|
|
|
|
|
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
|
|
|
|
|
if (crtc_state->ips_enabled)
|
|
|
|
|
pixclk = DIV_ROUND_UP(pixclk * 100, 95);
|
|
|
|
|
} else if (IS_VALLEYVIEW(dev_priv) ||
|
|
|
|
|
IS_CHERRYVIEW(dev_priv) ||
|
|
|
|
|
IS_BROXTON(dev_priv))
|
|
|
|
|
pixclk = crtc_state->base.adjusted_mode.crtc_clock;
|
|
|
|
|
else
|
|
|
|
|
WARN_ON(dev_priv->display.modeset_calc_cdclk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev_priv->min_pixclk[crtc->pipe] = pixclk;
|
2015-04-21 17:12:53 +03:00
|
|
|
|
2015-09-10 18:59:08 +03:00
|
|
|
readout_plane_state(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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
|
|
|
|
|
crtc->base.base.id,
|
|
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 13:34:16 +02:00
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
|
|
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
|
|
|
|
|
2014-10-29 11:32:32 +02:00
|
|
|
pll->on = pll->get_hw_state(dev_priv, pll,
|
|
|
|
|
&pll->config.hw_state);
|
2013-06-05 13:34:16 +02:00
|
|
|
pll->active = 0;
|
2014-10-29 11:32:32 +02:00
|
|
|
pll->config.crtc_mask = 0;
|
2014-05-13 23:32:22 +01:00
|
|
|
for_each_intel_crtc(dev, crtc) {
|
2014-10-29 11:32:31 +02:00
|
|
|
if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) {
|
2013-06-05 13:34:16 +02:00
|
|
|
pll->active++;
|
2014-10-29 11:32:32 +02:00
|
|
|
pll->config.crtc_mask |= 1 << crtc->pipe;
|
2014-10-29 11:32:31 +02:00
|
|
|
}
|
2013-06-05 13:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-29 11:32:31 +02:00
|
|
|
DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n",
|
2014-10-29 11:32:32 +02:00
|
|
|
pll->name, pll->config.crtc_mask, pll->on);
|
2014-07-04 11:27:38 -03:00
|
|
|
|
2014-10-29 11:32:32 +02:00
|
|
|
if (pll->config.crtc_mask)
|
2014-07-04 11:27:38 -03:00
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
|
2013-06-05 13:34:16 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
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-02 20:28:59 +02:00
|
|
|
pipe = 0;
|
|
|
|
|
|
|
|
|
|
if (encoder->get_hw_state(encoder, &pipe)) {
|
2013-05-14 17:08:26 -07:00
|
|
|
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
|
|
encoder->base.crtc = &crtc->base;
|
2015-01-15 14:55:25 +02:00
|
|
|
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-02 20:28:59 +02:00
|
|
|
} else {
|
|
|
|
|
encoder->base.crtc = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 12:29:54 +01:00
|
|
|
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
|
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-02 20:28:59 +02:00
|
|
|
encoder->base.base.id,
|
2014-06-03 14:56:21 +03:00
|
|
|
encoder->base.name,
|
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-02 20:28:59 +02:00
|
|
|
encoder->base.crtc ? "enabled" : "disabled",
|
2013-10-16 12:29:54 +01:00
|
|
|
pipe_name(pipe));
|
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-02 20:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-03 15:21:56 +02:00
|
|
|
for_each_intel_connector(dev, connector) {
|
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-02 20:28:59 +02:00
|
|
|
if (connector->get_hw_state(connector)) {
|
|
|
|
|
connector->base.dpms = DRM_MODE_DPMS_ON;
|
|
|
|
|
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,
|
2014-06-03 14:56:17 +03:00
|
|
|
connector->base.name,
|
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-02 20:28:59 +02:00
|
|
|
connector->base.encoder ? "enabled" : "disabled");
|
|
|
|
|
}
|
2015-09-10 18:59:07 +03:00
|
|
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc) {
|
|
|
|
|
crtc->base.hwmode = crtc->config->base.adjusted_mode;
|
|
|
|
|
|
|
|
|
|
memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
|
|
|
|
|
if (crtc->base.state->active) {
|
|
|
|
|
intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
|
|
|
|
|
intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
|
|
|
|
|
WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The initial mode needs to be set in order to keep
|
|
|
|
|
* the atomic core happy. It wants a valid mode if the
|
|
|
|
|
* crtc's enabled, so we do the above call.
|
|
|
|
|
*
|
|
|
|
|
* At this point some state updated by the connectors
|
|
|
|
|
* in their ->detect() callback has not run yet, so
|
|
|
|
|
* no recalculation can be done yet.
|
|
|
|
|
*
|
|
|
|
|
* Even if we could do a recalculation and modeset
|
|
|
|
|
* right now it would cause a double modeset if
|
|
|
|
|
* fbdev or userspace chooses a different initial mode.
|
|
|
|
|
*
|
|
|
|
|
* If that happens, someone indicated they wanted a
|
|
|
|
|
* mode change, which means it's safe to do a full
|
|
|
|
|
* recalculation.
|
|
|
|
|
*/
|
|
|
|
|
crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
|
2015-09-10 18:59:10 +03:00
|
|
|
|
|
|
|
|
drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
|
|
|
|
|
update_scanline_offset(crtc);
|
2015-09-10 18:59:07 +03:00
|
|
|
}
|
|
|
|
|
}
|
2013-06-05 13:34:17 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-13 16:30:25 +02:00
|
|
|
/* Scan out the current hw modeset state,
|
|
|
|
|
* and sanitizes it to the current state
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
intel_modeset_setup_hw_state(struct drm_device *dev)
|
2013-06-05 13:34:17 +02:00
|
|
|
{
|
|
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
enum pipe pipe;
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
struct intel_encoder *encoder;
|
2013-07-17 06:55:04 +02:00
|
|
|
int i;
|
2013-06-05 13:34:17 +02:00
|
|
|
|
|
|
|
|
intel_modeset_readout_hw_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-02 20:28:59 +02:00
|
|
|
|
|
|
|
|
/* HW state is read out, now we need to sanitize this mess. */
|
2014-08-05 11:29:37 +01:00
|
|
|
for_each_intel_encoder(dev, encoder) {
|
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-02 20:28:59 +02:00
|
|
|
intel_sanitize_encoder(encoder);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-18 13:49:10 +01:00
|
|
|
for_each_pipe(dev_priv, pipe) {
|
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-02 20:28:59 +02:00
|
|
|
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
|
|
intel_sanitize_crtc(crtc);
|
2015-01-15 14:55:25 +02: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-02 20:28:59 +02: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-05 22:34:27 +02:00
|
|
|
|
2015-03-20 16:18:05 +02:00
|
|
|
intel_modeset_update_connector_atomic_state(dev);
|
|
|
|
|
|
2013-07-17 06:55:04 +02:00
|
|
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
|
|
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
|
|
|
|
|
|
|
|
|
if (!pll->on || pll->active)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
|
|
|
|
|
|
|
|
|
|
pll->disable(dev_priv, pll);
|
|
|
|
|
pll->on = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-09 12:29:35 -08:00
|
|
|
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
2015-06-24 22:00:03 +03:00
|
|
|
vlv_wm_get_hw_state(dev);
|
|
|
|
|
else if (IS_GEN9(dev))
|
2014-11-04 17:06:45 +00:00
|
|
|
skl_wm_get_hw_state(dev);
|
|
|
|
|
else if (HAS_PCH_SPLIT(dev))
|
2013-10-14 14:55:24 +03:00
|
|
|
ilk_wm_get_hw_state(dev);
|
2015-07-13 16:30:27 +02:00
|
|
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc) {
|
|
|
|
|
unsigned long put_domains;
|
|
|
|
|
|
|
|
|
|
put_domains = modeset_get_crtc_power_domains(&crtc->base);
|
|
|
|
|
if (WARN_ON(put_domains))
|
|
|
|
|
modeset_put_power_domains(dev_priv, put_domains);
|
|
|
|
|
}
|
|
|
|
|
intel_display_set_init_power(dev_priv, false);
|
2015-07-13 16:30:25 +02:00
|
|
|
}
|
2013-09-16 17:38:33 +03:00
|
|
|
|
2015-07-13 16:30:25 +02:00
|
|
|
void intel_display_resume(struct drm_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct drm_atomic_state *state = drm_atomic_state_alloc(dev);
|
|
|
|
|
struct intel_connector *conn;
|
|
|
|
|
struct intel_plane *plane;
|
|
|
|
|
struct drm_crtc *crtc;
|
|
|
|
|
int ret;
|
2013-04-11 20:22:50 +02:00
|
|
|
|
2015-07-13 16:30:25 +02:00
|
|
|
if (!state)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
state->acquire_ctx = dev->mode_config.acquire_ctx;
|
|
|
|
|
|
|
|
|
|
/* preserve complete old state, including dpll */
|
|
|
|
|
intel_atomic_get_shared_dpll_state(state);
|
|
|
|
|
|
|
|
|
|
for_each_crtc(dev, crtc) {
|
|
|
|
|
struct drm_crtc_state *crtc_state =
|
|
|
|
|
drm_atomic_get_crtc_state(state, crtc);
|
|
|
|
|
|
|
|
|
|
ret = PTR_ERR_OR_ZERO(crtc_state);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
/* force a restore */
|
|
|
|
|
crtc_state->mode_changed = true;
|
2012-11-23 18:16:34 +01:00
|
|
|
}
|
2012-07-10 09:50:11 +02:00
|
|
|
|
2015-07-13 16:30:25 +02:00
|
|
|
for_each_intel_plane(dev, plane) {
|
|
|
|
|
ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, &plane->base));
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for_each_intel_connector(dev, conn) {
|
|
|
|
|
ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, &conn->base));
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intel_modeset_setup_hw_state(dev);
|
|
|
|
|
|
|
|
|
|
i915_redisable_vga(dev);
|
2015-07-13 16:30:30 +02:00
|
|
|
ret = drm_atomic_commit(state);
|
2015-07-13 16:30:25 +02:00
|
|
|
if (!ret)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
DRM_ERROR("Restoring old state failed with %i\n", ret);
|
|
|
|
|
drm_atomic_state_free(state);
|
2011-03-29 10:40:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void intel_modeset_gem_init(struct drm_device *dev)
|
|
|
|
|
{
|
2014-03-07 08:57:55 -08:00
|
|
|
struct drm_crtc *c;
|
2014-07-08 07:50:07 -07:00
|
|
|
struct drm_i915_gem_object *obj;
|
2015-04-13 16:03:03 +01:00
|
|
|
int ret;
|
2014-03-07 08:57:55 -08:00
|
|
|
|
2014-03-31 15:10:44 +03:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
intel_init_gt_powersave(dev);
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
2012-05-09 11:56:28 +01:00
|
|
|
intel_modeset_init_hw(dev);
|
2009-09-15 22:57:34 +02:00
|
|
|
|
|
|
|
|
intel_setup_overlay(dev);
|
2014-03-07 08:57:55 -08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure any fbs we allocated at startup are properly
|
|
|
|
|
* pinned & fenced. When we do the allocation it's too early
|
|
|
|
|
* for this.
|
|
|
|
|
*/
|
2014-05-13 23:32:24 +01:00
|
|
|
for_each_crtc(dev, c) {
|
2014-07-08 07:50:07 -07:00
|
|
|
obj = intel_fb_obj(c->primary->fb);
|
|
|
|
|
if (obj == NULL)
|
2014-03-07 08:57:55 -08:00
|
|
|
continue;
|
|
|
|
|
|
2015-04-13 16:03:03 +01:00
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
ret = intel_pin_and_fence_fb_obj(c->primary,
|
|
|
|
|
c->primary->fb,
|
2015-08-18 13:40:06 +02:00
|
|
|
c->primary->state);
|
2015-04-13 16:03:03 +01:00
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
if (ret) {
|
2014-03-07 08:57:55 -08:00
|
|
|
DRM_ERROR("failed to pin boot fb on pipe %d\n",
|
|
|
|
|
to_intel_crtc(c)->pipe);
|
2014-04-03 07:51:54 +10:00
|
|
|
drm_framebuffer_unreference(c->primary->fb);
|
|
|
|
|
c->primary->fb = NULL;
|
2015-06-01 12:49:54 +02:00
|
|
|
c->primary->crtc = c->primary->state->crtc = NULL;
|
2015-02-03 13:10:04 -08:00
|
|
|
update_state_fb(c->primary);
|
2015-06-01 12:49:54 +02:00
|
|
|
c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
|
2014-03-07 08:57:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
2014-11-07 15:19:46 +02:00
|
|
|
|
|
|
|
|
intel_backlight_register(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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2014-02-11 17:12:48 +02:00
|
|
|
void intel_connector_unregister(struct intel_connector *intel_connector)
|
|
|
|
|
{
|
|
|
|
|
struct drm_connector *connector = &intel_connector->base;
|
|
|
|
|
|
|
|
|
|
intel_panel_destroy_backlight(connector);
|
2014-05-29 16:57:41 +01:00
|
|
|
drm_connector_unregister(connector);
|
2014-02-11 17:12:48 +02: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-07 14:24:08 -08:00
|
|
|
void intel_modeset_cleanup(struct drm_device *dev)
|
|
|
|
|
{
|
2009-08-17 13:31:43 -07:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2015-12-16 12:48:16 +02:00
|
|
|
struct intel_connector *connector;
|
2009-08-17 13:31:43 -07:00
|
|
|
|
2014-11-19 15:30:05 +02:00
|
|
|
intel_disable_gt_powersave(dev);
|
|
|
|
|
|
2014-11-07 15:19:46 +02:00
|
|
|
intel_backlight_unregister(dev);
|
|
|
|
|
|
2013-04-24 11:13:35 +02:00
|
|
|
/*
|
|
|
|
|
* Interrupts and polling as the first thing to avoid creating havoc.
|
2014-11-19 15:30:05 +02:00
|
|
|
* Too much stuff here (turning of connectors, ...) would
|
2013-04-24 11:13:35 +02:00
|
|
|
* experience fancy races otherwise.
|
|
|
|
|
*/
|
2014-09-30 10:56:43 +02:00
|
|
|
intel_irq_uninstall(dev_priv);
|
2014-06-20 11:57:33 -07:00
|
|
|
|
2013-04-24 11:13:35 +02:00
|
|
|
/*
|
|
|
|
|
* 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-03 19:36:26 -07:00
|
|
|
drm_kms_helper_poll_fini(dev);
|
2013-04-24 11:13:35 +02:00
|
|
|
|
2010-10-07 16:01:13 -07:00
|
|
|
intel_unregister_dsm_handler();
|
|
|
|
|
|
2015-07-07 15:26:04 -03:00
|
|
|
intel_fbc_disable(dev_priv);
|
2009-11-11 12:19:17 -05:00
|
|
|
|
2011-07-08 12:22:42 +01:00
|
|
|
/* flush any delayed tasks or pending work */
|
|
|
|
|
flush_scheduled_work();
|
|
|
|
|
|
2013-11-08 16:48:53 +02:00
|
|
|
/* destroy the backlight and sysfs files before encoders/connectors */
|
2015-12-16 12:48:16 +02:00
|
|
|
for_each_intel_connector(dev, connector)
|
|
|
|
|
connector->unregister(connector);
|
2013-09-26 20:05:59 -03: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-07 14:24:08 -08:00
|
|
|
drm_mode_config_cleanup(dev);
|
2012-12-18 15:24:37 +01:00
|
|
|
|
|
|
|
|
intel_cleanup_overlay(dev);
|
2014-03-31 15:10:44 +03:00
|
|
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
intel_cleanup_gt_powersave(dev);
|
|
|
|
|
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-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
|
2010-03-30 14:39:29 +08:00
|
|
|
/*
|
|
|
|
|
* Return which encoder is currently attached for connector.
|
|
|
|
|
*/
|
2010-09-09 16:20:55 +01: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-07 14:24:08 -08:00
|
|
|
{
|
2010-09-09 16:20:55 +01:00
|
|
|
return &intel_attached_encoder(connector)->base;
|
|
|
|
|
}
|
2010-03-30 14:39:29 +08:00
|
|
|
|
2010-09-09 16:20:55 +01: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-07 14:24:08 -08:00
|
|
|
}
|
2009-09-21 14:33:58 +10: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;
|
2013-12-17 14:34:50 +00:00
|
|
|
unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
|
2009-09-21 14:33:58 +10:00
|
|
|
u16 gmch_ctrl;
|
|
|
|
|
|
2014-02-07 18:37:02 -02:00
|
|
|
if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
|
|
|
|
|
DRM_ERROR("failed to read control word\n");
|
|
|
|
|
return -EIO;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-07 18:37:03 -02:00
|
|
|
if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !state)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2009-09-21 14:33:58 +10:00
|
|
|
if (state)
|
|
|
|
|
gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
|
|
|
|
|
else
|
|
|
|
|
gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
|
2014-02-07 18:37:02 -02:00
|
|
|
|
|
|
|
|
if (pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl)) {
|
|
|
|
|
DRM_ERROR("failed to write control word\n");
|
|
|
|
|
return -EIO;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-21 14:33:58 +10:00
|
|
|
return 0;
|
|
|
|
|
}
|
2010-11-21 13:12:35 +00:00
|
|
|
|
|
|
|
|
struct intel_display_error_state {
|
2013-05-03 12:15:37 -03:00
|
|
|
|
|
|
|
|
u32 power_well_driver;
|
|
|
|
|
|
2013-08-08 15:12:06 +02:00
|
|
|
int num_transcoders;
|
|
|
|
|
|
2010-11-21 13:12:35 +00:00
|
|
|
struct intel_cursor_error_state {
|
|
|
|
|
u32 control;
|
|
|
|
|
u32 position;
|
|
|
|
|
u32 base;
|
|
|
|
|
u32 size;
|
2012-08-15 19:23:25 +01:00
|
|
|
} cursor[I915_MAX_PIPES];
|
2010-11-21 13:12:35 +00:00
|
|
|
|
|
|
|
|
struct intel_pipe_error_state {
|
2013-11-27 22:02:02 +02:00
|
|
|
bool power_domain_on;
|
2010-11-21 13:12:35 +00:00
|
|
|
u32 source;
|
2014-04-18 15:55:04 +03:00
|
|
|
u32 stat;
|
2012-08-15 19:23:25 +01:00
|
|
|
} pipe[I915_MAX_PIPES];
|
2010-11-21 13:12:35 +00:00
|
|
|
|
|
|
|
|
struct intel_plane_error_state {
|
|
|
|
|
u32 control;
|
|
|
|
|
u32 stride;
|
|
|
|
|
u32 size;
|
|
|
|
|
u32 pos;
|
|
|
|
|
u32 addr;
|
|
|
|
|
u32 surface;
|
|
|
|
|
u32 tile_offset;
|
2012-08-15 19:23:25 +01:00
|
|
|
} plane[I915_MAX_PIPES];
|
2013-08-08 15:12:06 +02:00
|
|
|
|
|
|
|
|
struct intel_transcoder_error_state {
|
2013-11-27 22:02:02 +02:00
|
|
|
bool power_domain_on;
|
2013-08-08 15:12:06 +02:00
|
|
|
enum transcoder cpu_transcoder;
|
|
|
|
|
|
|
|
|
|
u32 conf;
|
|
|
|
|
|
|
|
|
|
u32 htotal;
|
|
|
|
|
u32 hblank;
|
|
|
|
|
u32 hsync;
|
|
|
|
|
u32 vtotal;
|
|
|
|
|
u32 vblank;
|
|
|
|
|
u32 vsync;
|
|
|
|
|
} transcoder[4];
|
2010-11-21 13:12:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct intel_display_error_state *
|
|
|
|
|
intel_display_capture_error_state(struct drm_device *dev)
|
|
|
|
|
{
|
2014-03-31 14:27:18 +03:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-11-21 13:12:35 +00:00
|
|
|
struct intel_display_error_state *error;
|
2013-08-08 15:12:06 +02:00
|
|
|
int transcoders[] = {
|
|
|
|
|
TRANSCODER_A,
|
|
|
|
|
TRANSCODER_B,
|
|
|
|
|
TRANSCODER_C,
|
|
|
|
|
TRANSCODER_EDP,
|
|
|
|
|
};
|
2010-11-21 13:12:35 +00:00
|
|
|
int i;
|
|
|
|
|
|
2013-08-08 15:12:06 +02:00
|
|
|
if (INTEL_INFO(dev)->num_pipes == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2013-11-01 13:32:08 -02:00
|
|
|
error = kzalloc(sizeof(*error), GFP_ATOMIC);
|
2010-11-21 13:12:35 +00:00
|
|
|
if (error == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2013-11-25 17:15:31 +02:00
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
2013-05-03 12:15:37 -03:00
|
|
|
error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
|
|
|
|
|
|
2014-08-18 13:49:10 +01:00
|
|
|
for_each_pipe(dev_priv, i) {
|
2013-11-27 22:02:02 +02:00
|
|
|
error->pipe[i].power_domain_on =
|
2014-09-30 10:56:39 +02:00
|
|
|
__intel_display_power_is_enabled(dev_priv,
|
|
|
|
|
POWER_DOMAIN_PIPE(i));
|
2013-11-27 22:02:02 +02:00
|
|
|
if (!error->pipe[i].power_domain_on)
|
2013-11-01 13:32:08 -02:00
|
|
|
continue;
|
|
|
|
|
|
2014-04-09 13:28:53 +03:00
|
|
|
error->cursor[i].control = I915_READ(CURCNTR(i));
|
|
|
|
|
error->cursor[i].position = I915_READ(CURPOS(i));
|
|
|
|
|
error->cursor[i].base = I915_READ(CURBASE(i));
|
2010-11-21 13:12:35 +00:00
|
|
|
|
|
|
|
|
error->plane[i].control = I915_READ(DSPCNTR(i));
|
|
|
|
|
error->plane[i].stride = I915_READ(DSPSTRIDE(i));
|
2013-03-22 14:20:57 -03:00
|
|
|
if (INTEL_INFO(dev)->gen <= 3) {
|
2013-03-06 20:03:13 -03:00
|
|
|
error->plane[i].size = I915_READ(DSPSIZE(i));
|
2013-03-22 14:20:57 -03:00
|
|
|
error->plane[i].pos = I915_READ(DSPPOS(i));
|
|
|
|
|
}
|
2013-03-06 20:03:14 -03:00
|
|
|
if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
|
|
|
|
|
error->plane[i].addr = I915_READ(DSPADDR(i));
|
2010-11-21 13:12:35 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
|
|
error->plane[i].surface = I915_READ(DSPSURF(i));
|
|
|
|
|
error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error->pipe[i].source = I915_READ(PIPESRC(i));
|
2014-04-18 15:55:04 +03:00
|
|
|
|
2014-07-21 15:23:43 +05:30
|
|
|
if (HAS_GMCH_DISPLAY(dev))
|
2014-04-18 15:55:04 +03:00
|
|
|
error->pipe[i].stat = I915_READ(PIPESTAT(i));
|
2013-08-08 15:12:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error->num_transcoders = INTEL_INFO(dev)->num_pipes;
|
|
|
|
|
if (HAS_DDI(dev_priv->dev))
|
|
|
|
|
error->num_transcoders++; /* Account for eDP. */
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < error->num_transcoders; i++) {
|
|
|
|
|
enum transcoder cpu_transcoder = transcoders[i];
|
|
|
|
|
|
2013-11-27 22:02:02 +02:00
|
|
|
error->transcoder[i].power_domain_on =
|
2014-09-30 10:56:39 +02:00
|
|
|
__intel_display_power_is_enabled(dev_priv,
|
2013-12-20 15:09:41 -02:00
|
|
|
POWER_DOMAIN_TRANSCODER(cpu_transcoder));
|
2013-11-27 22:02:02 +02:00
|
|
|
if (!error->transcoder[i].power_domain_on)
|
2013-11-01 13:32:08 -02:00
|
|
|
continue;
|
|
|
|
|
|
2013-08-08 15:12:06 +02:00
|
|
|
error->transcoder[i].cpu_transcoder = cpu_transcoder;
|
|
|
|
|
|
|
|
|
|
error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
|
|
|
|
|
error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
|
2010-11-21 13:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-23 13:55:35 +03:00
|
|
|
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
|
|
|
|
|
|
2010-11-21 13:12:35 +00:00
|
|
|
void
|
2013-05-23 13:55:35 +03:00
|
|
|
intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
2010-11-21 13:12:35 +00:00
|
|
|
struct drm_device *dev,
|
|
|
|
|
struct intel_display_error_state *error)
|
|
|
|
|
{
|
2014-08-18 13:49:10 +01:00
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
2010-11-21 13:12:35 +00:00
|
|
|
int i;
|
|
|
|
|
|
2013-08-08 15:12:06 +02:00
|
|
|
if (!error)
|
|
|
|
|
return;
|
|
|
|
|
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
|
2013-11-25 17:15:31 +02:00
|
|
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, "PWR_WELL_CTL2: %08x\n",
|
2013-05-03 12:15:37 -03:00
|
|
|
error->power_well_driver);
|
2014-08-18 13:49:10 +01:00
|
|
|
for_each_pipe(dev_priv, i) {
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, "Pipe [%d]:\n", i);
|
2013-11-27 22:02:02 +02:00
|
|
|
err_printf(m, " Power: %s\n",
|
|
|
|
|
error->pipe[i].power_domain_on ? "on" : "off");
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, " SRC: %08x\n", error->pipe[i].source);
|
2014-04-18 15:55:04 +03:00
|
|
|
err_printf(m, " STAT: %08x\n", error->pipe[i].stat);
|
2013-05-23 13:55:35 +03:00
|
|
|
|
|
|
|
|
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-22 14:20:57 -03:00
|
|
|
if (INTEL_INFO(dev)->gen <= 3) {
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, " SIZE: %08x\n", error->plane[i].size);
|
|
|
|
|
err_printf(m, " POS: %08x\n", error->plane[i].pos);
|
2013-03-22 14:20:57 -03:00
|
|
|
}
|
2013-03-22 14:19:21 -03:00
|
|
|
if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
|
2013-05-23 13:55:35 +03:00
|
|
|
err_printf(m, " ADDR: %08x\n", error->plane[i].addr);
|
2010-11-21 13:12:35 +00:00
|
|
|
if (INTEL_INFO(dev)->gen >= 4) {
|
2013-05-23 13:55:35 +03: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 13:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-23 13:55:35 +03: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 13:12:35 +00:00
|
|
|
}
|
2013-08-08 15:12:06 +02:00
|
|
|
|
|
|
|
|
for (i = 0; i < error->num_transcoders; i++) {
|
2013-10-21 09:10:33 +01:00
|
|
|
err_printf(m, "CPU transcoder: %c\n",
|
2013-08-08 15:12:06 +02:00
|
|
|
transcoder_name(error->transcoder[i].cpu_transcoder));
|
2013-11-27 22:02:02 +02:00
|
|
|
err_printf(m, " Power: %s\n",
|
|
|
|
|
error->transcoder[i].power_domain_on ? "on" : "off");
|
2013-08-08 15:12:06 +02:00
|
|
|
err_printf(m, " CONF: %08x\n", error->transcoder[i].conf);
|
|
|
|
|
err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal);
|
|
|
|
|
err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank);
|
|
|
|
|
err_printf(m, " HSYNC: %08x\n", error->transcoder[i].hsync);
|
|
|
|
|
err_printf(m, " VTOTAL: %08x\n", error->transcoder[i].vtotal);
|
|
|
|
|
err_printf(m, " VBLANK: %08x\n", error->transcoder[i].vblank);
|
|
|
|
|
err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
|
|
|
|
|
}
|
2010-11-21 13:12:35 +00:00
|
|
|
}
|
2014-08-06 14:02:51 +03:00
|
|
|
|
|
|
|
|
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
|
|
|
|
|
{
|
|
|
|
|
struct intel_crtc *crtc;
|
|
|
|
|
|
|
|
|
|
for_each_intel_crtc(dev, crtc) {
|
|
|
|
|
struct intel_unpin_work *work;
|
|
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_lock_irq(&dev->event_lock);
|
2014-08-06 14:02:51 +03:00
|
|
|
|
|
|
|
|
work = crtc->unpin_work;
|
|
|
|
|
|
|
|
|
|
if (work && work->event &&
|
|
|
|
|
work->event->base.file_priv == file) {
|
|
|
|
|
kfree(work->event);
|
|
|
|
|
work->event = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 14:55:22 +02:00
|
|
|
spin_unlock_irq(&dev->event_lock);
|
2014-08-06 14:02:51 +03:00
|
|
|
}
|
|
|
|
|
}
|