Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~keithp/linux

* 'drm-intel-fixes' of git://people.freedesktop.org/~keithp/linux:
  drm/i915/dp: Dither down to 6bpc if it makes the mode fit
  drm/i915: enable semaphores on per-device defaults
  drm/i915: don't set unpin_work if vblank_get fails
  drm/i915: By default, enable RC6 on IVB and SNB when reasonable
  iommu: Export intel_iommu_enabled to signal when iommu is in use
  drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check
  drm/i915: prevent division by zero when asking for chipset power
  drm/i915: add PCH info to i915_capabilities
  drm/i915: set the right SDVO transcoder for CPT
  drm/i915: no-lvds quirk for ASUS AT5NM10T-I
  drm/i915: Treat pre-gen4 backlight duty cycle value consistently
  drm/i915: Hook up Ivybridge eDP
  drm/i915: add multi-threaded forcewake support
This commit is contained in:
Linus Torvalds 2011-12-16 11:27:56 -08:00
commit 2cfab8d74e
14 changed files with 361 additions and 90 deletions

View File

@ -62,6 +62,7 @@ static int i915_capabilities(struct seq_file *m, void *data)
const struct intel_device_info *info = INTEL_INFO(dev); const struct intel_device_info *info = INTEL_INFO(dev);
seq_printf(m, "gen: %d\n", info->gen); seq_printf(m, "gen: %d\n", info->gen);
seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
#define B(x) seq_printf(m, #x ": %s\n", yesno(info->x)) #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
B(is_mobile); B(is_mobile);
B(is_i85x); B(is_i85x);

View File

@ -1454,6 +1454,14 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
diff1 = now - dev_priv->last_time1; diff1 = now - dev_priv->last_time1;
/* Prevent division-by-zero if we are asking too fast.
* Also, we don't get interesting results if we are polling
* faster than once in 10ms, so just return the saved value
* in such cases.
*/
if (diff1 <= 10)
return dev_priv->chipset_power;
count1 = I915_READ(DMIEC); count1 = I915_READ(DMIEC);
count2 = I915_READ(DDREC); count2 = I915_READ(DDREC);
count3 = I915_READ(CSIEC); count3 = I915_READ(CSIEC);
@ -1484,6 +1492,8 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
dev_priv->last_count1 = total_count; dev_priv->last_count1 = total_count;
dev_priv->last_time1 = now; dev_priv->last_time1 = now;
dev_priv->chipset_power = ret;
return ret; return ret;
} }

View File

@ -58,15 +58,15 @@ module_param_named(powersave, i915_powersave, int, 0600);
MODULE_PARM_DESC(powersave, MODULE_PARM_DESC(powersave,
"Enable powersavings, fbc, downclocking, etc. (default: true)"); "Enable powersavings, fbc, downclocking, etc. (default: true)");
unsigned int i915_semaphores __read_mostly = 0; int i915_semaphores __read_mostly = -1;
module_param_named(semaphores, i915_semaphores, int, 0600); module_param_named(semaphores, i915_semaphores, int, 0600);
MODULE_PARM_DESC(semaphores, MODULE_PARM_DESC(semaphores,
"Use semaphores for inter-ring sync (default: false)"); "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
unsigned int i915_enable_rc6 __read_mostly = 0; int i915_enable_rc6 __read_mostly = -1;
module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
MODULE_PARM_DESC(i915_enable_rc6, MODULE_PARM_DESC(i915_enable_rc6,
"Enable power-saving render C-state 6 (default: true)"); "Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
int i915_enable_fbc __read_mostly = -1; int i915_enable_fbc __read_mostly = -1;
module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
@ -328,7 +328,7 @@ void intel_detect_pch(struct drm_device *dev)
} }
} }
static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{ {
int count; int count;
@ -344,6 +344,22 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
udelay(10); udelay(10);
} }
void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
{
int count;
count = 0;
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
udelay(10);
I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
POSTING_READ(FORCEWAKE_MT);
count = 0;
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
udelay(10);
}
/* /*
* Generally this is called implicitly by the register read function. However, * Generally this is called implicitly by the register read function. However,
* if some sequence requires the GT to not power down then this function should * if some sequence requires the GT to not power down then this function should
@ -356,15 +372,21 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
/* Forcewake is atomic in case we get in here without the lock */ /* Forcewake is atomic in case we get in here without the lock */
if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
__gen6_gt_force_wake_get(dev_priv); dev_priv->display.force_wake_get(dev_priv);
} }
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{ {
I915_WRITE_NOTRACE(FORCEWAKE, 0); I915_WRITE_NOTRACE(FORCEWAKE, 0);
POSTING_READ(FORCEWAKE); POSTING_READ(FORCEWAKE);
} }
void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
{
I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
POSTING_READ(FORCEWAKE_MT);
}
/* /*
* see gen6_gt_force_wake_get() * see gen6_gt_force_wake_get()
*/ */
@ -373,7 +395,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
if (atomic_dec_and_test(&dev_priv->forcewake_count)) if (atomic_dec_and_test(&dev_priv->forcewake_count))
__gen6_gt_force_wake_put(dev_priv); dev_priv->display.force_wake_put(dev_priv);
} }
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@ -903,8 +925,9 @@ MODULE_LICENSE("GPL and additional rights");
/* We give fast paths for the really cool registers */ /* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \ #define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \ (((dev_priv)->info->gen >= 6) && \
((reg) < 0x40000) && \ ((reg) < 0x40000) && \
((reg) != FORCEWAKE)) ((reg) != FORCEWAKE) && \
((reg) != ECOBUS))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \

View File

@ -107,6 +107,7 @@ struct opregion_header;
struct opregion_acpi; struct opregion_acpi;
struct opregion_swsci; struct opregion_swsci;
struct opregion_asle; struct opregion_asle;
struct drm_i915_private;
struct intel_opregion { struct intel_opregion {
struct opregion_header *header; struct opregion_header *header;
@ -221,6 +222,8 @@ struct drm_i915_display_funcs {
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y); int x, int y);
void (*force_wake_get)(struct drm_i915_private *dev_priv);
void (*force_wake_put)(struct drm_i915_private *dev_priv);
/* clock updates for mode set */ /* clock updates for mode set */
/* cursor updates */ /* cursor updates */
/* render clock increase/decrease */ /* render clock increase/decrease */
@ -710,6 +713,7 @@ typedef struct drm_i915_private {
u64 last_count1; u64 last_count1;
unsigned long last_time1; unsigned long last_time1;
unsigned long chipset_power;
u64 last_count2; u64 last_count2;
struct timespec last_time2; struct timespec last_time2;
unsigned long gfx_power; unsigned long gfx_power;
@ -998,11 +1002,11 @@ extern int i915_max_ioctl;
extern unsigned int i915_fbpercrtc __always_unused; extern unsigned int i915_fbpercrtc __always_unused;
extern int i915_panel_ignore_lid __read_mostly; extern int i915_panel_ignore_lid __read_mostly;
extern unsigned int i915_powersave __read_mostly; extern unsigned int i915_powersave __read_mostly;
extern unsigned int i915_semaphores __read_mostly; extern int i915_semaphores __read_mostly;
extern unsigned int i915_lvds_downclock __read_mostly; extern unsigned int i915_lvds_downclock __read_mostly;
extern int i915_panel_use_ssc __read_mostly; extern int i915_panel_use_ssc __read_mostly;
extern int i915_vbt_sdvo_panel_type __read_mostly; extern int i915_vbt_sdvo_panel_type __read_mostly;
extern unsigned int i915_enable_rc6 __read_mostly; extern int i915_enable_rc6 __read_mostly;
extern int i915_enable_fbc __read_mostly; extern int i915_enable_fbc __read_mostly;
extern bool i915_enable_hangcheck __read_mostly; extern bool i915_enable_hangcheck __read_mostly;
@ -1308,6 +1312,11 @@ extern void gen6_set_rps(struct drm_device *dev, u8 val);
extern void intel_detect_pch(struct drm_device *dev); extern void intel_detect_pch(struct drm_device *dev);
extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
/* overlay */ /* overlay */
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@ -1352,8 +1361,9 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
/* We give fast paths for the really cool registers */ /* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \ #define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \ (((dev_priv)->info->gen >= 6) && \
((reg) < 0x40000) && \ ((reg) < 0x40000) && \
((reg) != FORCEWAKE)) ((reg) != FORCEWAKE) && \
((reg) != ECOBUS))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);

View File

@ -32,6 +32,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_drv.h" #include "intel_drv.h"
#include <linux/dma_remapping.h>
struct change_domains { struct change_domains {
uint32_t invalidate_domains; uint32_t invalidate_domains;
@ -746,6 +747,22 @@ i915_gem_execbuffer_flush(struct drm_device *dev,
return 0; return 0;
} }
static bool
intel_enable_semaphores(struct drm_device *dev)
{
if (INTEL_INFO(dev)->gen < 6)
return 0;
if (i915_semaphores >= 0)
return i915_semaphores;
/* Enable semaphores on SNB when IO remapping is off */
if (INTEL_INFO(dev)->gen == 6)
return !intel_iommu_enabled;
return 1;
}
static int static int
i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *to) struct intel_ring_buffer *to)
@ -758,7 +775,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
return 0; return 0;
/* XXX gpu semaphores are implicated in various hard hangs on SNB */ /* XXX gpu semaphores are implicated in various hard hangs on SNB */
if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores) if (!intel_enable_semaphores(obj->base.dev))
return i915_gem_object_wait_rendering(obj); return i915_gem_object_wait_rendering(obj);
idx = intel_ring_sync_index(from, to); idx = intel_ring_sync_index(from, to);

View File

@ -3303,10 +3303,10 @@
/* or SDVOB */ /* or SDVOB */
#define HDMIB 0xe1140 #define HDMIB 0xe1140
#define PORT_ENABLE (1 << 31) #define PORT_ENABLE (1 << 31)
#define TRANSCODER_A (0) #define TRANSCODER(pipe) ((pipe) << 30)
#define TRANSCODER_B (1 << 30) #define TRANSCODER_CPT(pipe) ((pipe) << 29)
#define TRANSCODER(pipe) ((pipe) << 30) #define TRANSCODER_MASK (1 << 30)
#define TRANSCODER_MASK (1 << 30) #define TRANSCODER_MASK_CPT (3 << 29)
#define COLOR_FORMAT_8bpc (0) #define COLOR_FORMAT_8bpc (0)
#define COLOR_FORMAT_12bpc (3 << 26) #define COLOR_FORMAT_12bpc (3 << 26)
#define SDVOB_HOTPLUG_ENABLE (1 << 23) #define SDVOB_HOTPLUG_ENABLE (1 << 23)
@ -3447,8 +3447,30 @@
#define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22) #define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22)
#define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) #define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22)
/* IVB */
#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 <<22)
#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a <<22)
#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f <<22)
#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22)
#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22)
#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22)
#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22)
/* legacy values */
#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22)
#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 <<22)
#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 <<22)
#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 <<22)
#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 <<22)
#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22)
#define FORCEWAKE 0xA18C #define FORCEWAKE 0xA18C
#define FORCEWAKE_ACK 0x130090 #define FORCEWAKE_ACK 0x130090
#define FORCEWAKE_MT 0xa188 /* multi-threaded */
#define FORCEWAKE_MT_ACK 0x130040
#define ECOBUS 0xa180
#define FORCEWAKE_MT_ENABLE (1<<5)
#define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_FREE_ENTRIES 0x120008
#define GT_FIFO_NUM_RESERVED_ENTRIES 20 #define GT_FIFO_NUM_RESERVED_ENTRIES 20

View File

@ -38,8 +38,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "drm_dp_helper.h" #include "drm_dp_helper.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
#include <linux/dma_remapping.h>
#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
@ -4670,6 +4670,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
/** /**
* intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
* @crtc: CRTC structure * @crtc: CRTC structure
* @mode: requested mode
* *
* A pipe may be connected to one or more outputs. Based on the depth of the * A pipe may be connected to one or more outputs. Based on the depth of the
* attached framebuffer, choose a good color depth to use on the pipe. * attached framebuffer, choose a good color depth to use on the pipe.
@ -4681,13 +4682,15 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
* HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
* Displays may support a restricted set as well, check EDID and clamp as * Displays may support a restricted set as well, check EDID and clamp as
* appropriate. * appropriate.
* DP may want to dither down to 6bpc to fit larger modes
* *
* RETURNS: * RETURNS:
* Dithering requirement (i.e. false if display bpc and pipe bpc match, * Dithering requirement (i.e. false if display bpc and pipe bpc match,
* true if they don't match). * true if they don't match).
*/ */
static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
unsigned int *pipe_bpp) unsigned int *pipe_bpp,
struct drm_display_mode *mode)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
@ -4758,6 +4761,11 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
} }
} }
if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
display_bpc = 6;
}
/* /*
* We could just drive the pipe at the highest bpc all the time and * We could just drive the pipe at the highest bpc all the time and
* enable dithering as needed, but that costs bandwidth. So choose * enable dithering as needed, but that costs bandwidth. So choose
@ -5019,6 +5027,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
pipeconf &= ~PIPECONF_DOUBLE_WIDE; pipeconf &= ~PIPECONF_DOUBLE_WIDE;
} }
/* default to 8bpc */
pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
if (is_dp) {
if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
pipeconf |= PIPECONF_BPP_6 |
PIPECONF_DITHER_EN |
PIPECONF_DITHER_TYPE_SP;
}
}
dpll |= DPLL_VCO_ENABLE; dpll |= DPLL_VCO_ENABLE;
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
@ -5480,7 +5498,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* determine panel color depth */ /* determine panel color depth */
temp = I915_READ(PIPECONF(pipe)); temp = I915_READ(PIPECONF(pipe));
temp &= ~PIPE_BPC_MASK; temp &= ~PIPE_BPC_MASK;
dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp); dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
switch (pipe_bpp) { switch (pipe_bpp) {
case 18: case 18:
temp |= PIPE_6BPC; temp |= PIPE_6BPC;
@ -7189,11 +7207,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->old_fb_obj = intel_fb->obj; work->old_fb_obj = intel_fb->obj;
INIT_WORK(&work->work, intel_unpin_work_fn); INIT_WORK(&work->work, intel_unpin_work_fn);
ret = drm_vblank_get(dev, intel_crtc->pipe);
if (ret)
goto free_work;
/* We borrow the event spin lock for protecting unpin_work */ /* We borrow the event spin lock for protecting unpin_work */
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work) { if (intel_crtc->unpin_work) {
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(work); kfree(work);
drm_vblank_put(dev, intel_crtc->pipe);
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
return -EBUSY; return -EBUSY;
@ -7212,10 +7235,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
crtc->fb = fb; crtc->fb = fb;
ret = drm_vblank_get(dev, intel_crtc->pipe);
if (ret)
goto cleanup_objs;
work->pending_flip_obj = obj; work->pending_flip_obj = obj;
work->enable_stall_check = true; work->enable_stall_check = true;
@ -7238,7 +7257,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_pending: cleanup_pending:
atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
cleanup_objs:
drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&work->old_fb_obj->base);
drm_gem_object_unreference(&obj->base); drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
@ -7247,6 +7265,8 @@ cleanup_objs:
intel_crtc->unpin_work = NULL; intel_crtc->unpin_work = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
drm_vblank_put(dev, intel_crtc->pipe);
free_work:
kfree(work); kfree(work);
return ret; return ret;
@ -7887,6 +7907,33 @@ void intel_init_emon(struct drm_device *dev)
dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
} }
static bool intel_enable_rc6(struct drm_device *dev)
{
/*
* Respect the kernel parameter if it is set
*/
if (i915_enable_rc6 >= 0)
return i915_enable_rc6;
/*
* Disable RC6 on Ironlake
*/
if (INTEL_INFO(dev)->gen == 5)
return 0;
/*
* Enable rc6 on Sandybridge if DMA remapping is disabled
*/
if (INTEL_INFO(dev)->gen == 6) {
DRM_DEBUG_DRIVER("Sandybridge: intel_iommu_enabled %s -- RC6 %sabled\n",
intel_iommu_enabled ? "true" : "false",
!intel_iommu_enabled ? "en" : "dis");
return !intel_iommu_enabled;
}
DRM_DEBUG_DRIVER("RC6 enabled\n");
return 1;
}
void gen6_enable_rps(struct drm_i915_private *dev_priv) void gen6_enable_rps(struct drm_i915_private *dev_priv)
{ {
u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@ -7923,7 +7970,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
if (i915_enable_rc6) if (intel_enable_rc6(dev_priv->dev))
rc6_mask = GEN6_RC_CTL_RC6p_ENABLE | rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
GEN6_RC_CTL_RC6_ENABLE; GEN6_RC_CTL_RC6_ENABLE;
@ -8372,7 +8419,7 @@ void ironlake_enable_rc6(struct drm_device *dev)
/* rc6 disabled by default due to repeated reports of hanging during /* rc6 disabled by default due to repeated reports of hanging during
* boot and resume. * boot and resume.
*/ */
if (!i915_enable_rc6) if (!intel_enable_rc6(dev))
return; return;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
@ -8491,6 +8538,28 @@ static void intel_init_display(struct drm_device *dev)
/* For FIFO watermark updates */ /* For FIFO watermark updates */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
/* IVB configs may use multi-threaded forcewake */
if (IS_IVYBRIDGE(dev)) {
u32 ecobus;
mutex_lock(&dev->struct_mutex);
__gen6_gt_force_wake_mt_get(dev_priv);
ecobus = I915_READ(ECOBUS);
__gen6_gt_force_wake_mt_put(dev_priv);
mutex_unlock(&dev->struct_mutex);
if (ecobus & FORCEWAKE_MT_ENABLE) {
DRM_DEBUG_KMS("Using MT version of forcewake\n");
dev_priv->display.force_wake_get =
__gen6_gt_force_wake_mt_get;
dev_priv->display.force_wake_put =
__gen6_gt_force_wake_mt_put;
}
}
if (HAS_PCH_IBX(dev)) if (HAS_PCH_IBX(dev))
dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
else if (HAS_PCH_CPT(dev)) else if (HAS_PCH_CPT(dev))

View File

@ -208,13 +208,15 @@ intel_dp_link_clock(uint8_t link_bw)
*/ */
static int static int
intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock) intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
{ {
struct drm_crtc *crtc = intel_dp->base.base.crtc; struct drm_crtc *crtc = intel_dp->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int bpp = 24; int bpp = 24;
if (intel_crtc) if (check_bpp)
bpp = check_bpp;
else if (intel_crtc)
bpp = intel_crtc->bpp; bpp = intel_crtc->bpp;
return (pixel_clock * bpp + 9) / 10; return (pixel_clock * bpp + 9) / 10;
@ -233,6 +235,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
int max_lanes = intel_dp_max_lane_count(intel_dp); int max_lanes = intel_dp_max_lane_count(intel_dp);
int max_rate, mode_rate;
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
@ -242,9 +245,17 @@ intel_dp_mode_valid(struct drm_connector *connector,
return MODE_PANEL; return MODE_PANEL;
} }
if (intel_dp_link_required(intel_dp, mode->clock) mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
> intel_dp_max_data_rate(max_link_clock, max_lanes)) max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
return MODE_CLOCK_HIGH;
if (mode_rate > max_rate) {
mode_rate = intel_dp_link_required(intel_dp,
mode->clock, 18);
if (mode_rate > max_rate)
return MODE_CLOCK_HIGH;
else
mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
}
if (mode->clock < 10000) if (mode->clock < 10000)
return MODE_CLOCK_LOW; return MODE_CLOCK_LOW;
@ -362,8 +373,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
* clock divider. * clock divider.
*/ */
if (is_cpu_edp(intel_dp)) { if (is_cpu_edp(intel_dp)) {
if (IS_GEN6(dev)) if (IS_GEN6(dev) || IS_GEN7(dev))
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
else else
aux_clock_divider = 225; /* eDP input clock at 450Mhz */ aux_clock_divider = 225; /* eDP input clock at 450Mhz */
} else if (HAS_PCH_SPLIT(dev)) } else if (HAS_PCH_SPLIT(dev))
@ -672,6 +683,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
int lane_count, clock; int lane_count, clock;
int max_lane_count = intel_dp_max_lane_count(intel_dp); int max_lane_count = intel_dp_max_lane_count(intel_dp);
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
@ -689,7 +701,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
for (clock = 0; clock <= max_clock; clock++) { for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
if (intel_dp_link_required(intel_dp, mode->clock) if (intel_dp_link_required(intel_dp, mode->clock, bpp)
<= link_avail) { <= link_avail) {
intel_dp->link_bw = bws[clock]; intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count; intel_dp->lane_count = lane_count;
@ -817,10 +829,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
} }
/* /*
* There are three kinds of DP registers: * There are four kinds of DP registers:
* *
* IBX PCH * IBX PCH
* CPU * SNB CPU
* IVB CPU
* CPT PCH * CPT PCH
* *
* IBX PCH and CPU are the same for almost everything, * IBX PCH and CPU are the same for almost everything,
@ -873,7 +886,25 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
/* Split out the IBX/CPU vs CPT settings */ /* Split out the IBX/CPU vs CPT settings */
if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
intel_dp->DP |= DP_SYNC_HS_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
intel_dp->DP |= DP_SYNC_VS_HIGH;
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
intel_dp->DP |= DP_ENHANCED_FRAMING;
intel_dp->DP |= intel_crtc->pipe << 29;
/* don't miss out required setting for eDP */
intel_dp->DP |= DP_PLL_ENABLE;
if (adjusted_mode->clock < 200000)
intel_dp->DP |= DP_PLL_FREQ_160MHZ;
else
intel_dp->DP |= DP_PLL_FREQ_270MHZ;
} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
intel_dp->DP |= intel_dp->color_range; intel_dp->DP |= intel_dp->color_range;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@ -1375,34 +1406,59 @@ static char *link_train_names[] = {
* These are source-specific values; current Intel hardware supports * These are source-specific values; current Intel hardware supports
* a maximum voltage of 800mV and a maximum pre-emphasis of 6dB * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
*/ */
#define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800
#define I830_DP_VOLTAGE_MAX_CPT DP_TRAIN_VOLTAGE_SWING_1200
static uint8_t static uint8_t
intel_dp_pre_emphasis_max(uint8_t voltage_swing) intel_dp_voltage_max(struct intel_dp *intel_dp)
{ {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { struct drm_device *dev = intel_dp->base.base.dev;
case DP_TRAIN_VOLTAGE_SWING_400:
return DP_TRAIN_PRE_EMPHASIS_6; if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
case DP_TRAIN_VOLTAGE_SWING_600: return DP_TRAIN_VOLTAGE_SWING_800;
return DP_TRAIN_PRE_EMPHASIS_6; else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
case DP_TRAIN_VOLTAGE_SWING_800: return DP_TRAIN_VOLTAGE_SWING_1200;
return DP_TRAIN_PRE_EMPHASIS_3_5; else
case DP_TRAIN_VOLTAGE_SWING_1200: return DP_TRAIN_VOLTAGE_SWING_800;
default: }
return DP_TRAIN_PRE_EMPHASIS_0;
static uint8_t
intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
{
struct drm_device *dev = intel_dp->base.base.dev;
if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_400:
return DP_TRAIN_PRE_EMPHASIS_6;
case DP_TRAIN_VOLTAGE_SWING_600:
case DP_TRAIN_VOLTAGE_SWING_800:
return DP_TRAIN_PRE_EMPHASIS_3_5;
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
} else {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_400:
return DP_TRAIN_PRE_EMPHASIS_6;
case DP_TRAIN_VOLTAGE_SWING_600:
return DP_TRAIN_PRE_EMPHASIS_6;
case DP_TRAIN_VOLTAGE_SWING_800:
return DP_TRAIN_PRE_EMPHASIS_3_5;
case DP_TRAIN_VOLTAGE_SWING_1200:
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
} }
} }
static void static void
intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
{ {
struct drm_device *dev = intel_dp->base.base.dev;
uint8_t v = 0; uint8_t v = 0;
uint8_t p = 0; uint8_t p = 0;
int lane; int lane;
uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS); uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
int voltage_max; uint8_t voltage_max;
uint8_t preemph_max;
for (lane = 0; lane < intel_dp->lane_count; lane++) { for (lane = 0; lane < intel_dp->lane_count; lane++) {
uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane); uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
@ -1414,15 +1470,13 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST
p = this_p; p = this_p;
} }
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) voltage_max = intel_dp_voltage_max(intel_dp);
voltage_max = I830_DP_VOLTAGE_MAX_CPT;
else
voltage_max = I830_DP_VOLTAGE_MAX;
if (v >= voltage_max) if (v >= voltage_max)
v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
if (p >= intel_dp_pre_emphasis_max(v)) preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; if (p >= preemph_max)
p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
for (lane = 0; lane < 4; lane++) for (lane = 0; lane < 4; lane++)
intel_dp->train_set[lane] = v | p; intel_dp->train_set[lane] = v | p;
@ -1494,6 +1548,37 @@ intel_gen6_edp_signal_levels(uint8_t train_set)
} }
} }
/* Gen7's DP voltage swing and pre-emphasis control */
static uint32_t
intel_gen7_edp_signal_levels(uint8_t train_set)
{
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
DP_TRAIN_PRE_EMPHASIS_MASK);
switch (signal_levels) {
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
return EDP_LINK_TRAIN_400MV_0DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
return EDP_LINK_TRAIN_400MV_6DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
return EDP_LINK_TRAIN_600MV_0DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
return EDP_LINK_TRAIN_800MV_0DB_IVB;
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
default:
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
"0x%x\n", signal_levels);
return EDP_LINK_TRAIN_500MV_0DB_IVB;
}
}
static uint8_t static uint8_t
intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
int lane) int lane)
@ -1599,7 +1684,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP_LINK_CONFIGURATION_SIZE); DP_LINK_CONFIGURATION_SIZE);
DP |= DP_PORT_EN; DP |= DP_PORT_EN;
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
else else
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
@ -1613,7 +1699,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
uint8_t link_status[DP_LINK_STATUS_SIZE]; uint8_t link_status[DP_LINK_STATUS_SIZE];
uint32_t signal_levels; uint32_t signal_levels;
if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } else {
@ -1622,7 +1712,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
reg = DP | DP_LINK_TRAIN_PAT_1_CPT; reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
else else
reg = DP | DP_LINK_TRAIN_PAT_1; reg = DP | DP_LINK_TRAIN_PAT_1;
@ -1703,7 +1793,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
break; break;
} }
if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } else {
@ -1711,7 +1804,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
reg = DP | DP_LINK_TRAIN_PAT_2_CPT; reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
else else
reg = DP | DP_LINK_TRAIN_PAT_2; reg = DP | DP_LINK_TRAIN_PAT_2;
@ -1752,7 +1845,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
++tries; ++tries;
} }
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
reg = DP | DP_LINK_TRAIN_OFF_CPT; reg = DP | DP_LINK_TRAIN_OFF_CPT;
else else
reg = DP | DP_LINK_TRAIN_OFF; reg = DP | DP_LINK_TRAIN_OFF;
@ -1782,7 +1875,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
udelay(100); udelay(100);
} }
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) { if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else { } else {
@ -1794,7 +1887,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
msleep(17); msleep(17);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
DP |= DP_LINK_TRAIN_OFF_CPT; DP |= DP_LINK_TRAIN_OFF_CPT;
else else
DP |= DP_LINK_TRAIN_OFF; DP |= DP_LINK_TRAIN_OFF;

View File

@ -110,6 +110,7 @@
/* drm_display_mode->private_flags */ /* drm_display_mode->private_flags */
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
#define INTEL_MODE_DP_FORCE_6BPC (0x10)
static inline void static inline void
intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,

View File

@ -715,6 +715,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
}, },
}, },
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Asus AT5NM10T-I",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
},
},
{ } /* terminating entry */ { } /* terminating entry */
}; };

View File

@ -178,13 +178,10 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
max >>= 16; max >>= 16;
} else { } else {
if (IS_PINEVIEW(dev)) { if (INTEL_INFO(dev)->gen < 4)
max >>= 17; max >>= 17;
} else { else
max >>= 16; max >>= 16;
if (INTEL_INFO(dev)->gen < 4)
max &= ~1;
}
if (is_backlight_combination_mode(dev)) if (is_backlight_combination_mode(dev))
max *= 0xff; max *= 0xff;
@ -203,13 +200,12 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
} else { } else {
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
if (IS_PINEVIEW(dev)) if (INTEL_INFO(dev)->gen < 4)
val >>= 1; val >>= 1;
if (is_backlight_combination_mode(dev)) { if (is_backlight_combination_mode(dev)) {
u8 lbpc; u8 lbpc;
val &= ~1;
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
val *= lbpc; val *= lbpc;
} }
@ -246,11 +242,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level
} }
tmp = I915_READ(BLC_PWM_CTL); tmp = I915_READ(BLC_PWM_CTL);
if (IS_PINEVIEW(dev)) { if (INTEL_INFO(dev)->gen < 4)
tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
level <<= 1; level <<= 1;
} else tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
I915_WRITE(BLC_PWM_CTL, tmp | level); I915_WRITE(BLC_PWM_CTL, tmp | level);
} }

View File

@ -50,6 +50,7 @@
#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK)
#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
static const char *tv_format_names[] = { static const char *tv_format_names[] = {
@ -1086,8 +1087,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
} }
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
} }
if (intel_crtc->pipe == 1)
sdvox |= SDVO_PIPE_B_SELECT; if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
sdvox |= TRANSCODER_CPT(intel_crtc->pipe);
else
sdvox |= TRANSCODER(intel_crtc->pipe);
if (intel_sdvo->has_hdmi_audio) if (intel_sdvo->has_hdmi_audio)
sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_AUDIO_ENABLE;
@ -1314,6 +1319,18 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
return status; return status;
} }
static bool
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
struct edid *edid)
{
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
bool connector_is_digital = !!IS_DIGITAL(sdvo);
DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
connector_is_digital, monitor_is_digital);
return connector_is_digital == monitor_is_digital;
}
static enum drm_connector_status static enum drm_connector_status
intel_sdvo_detect(struct drm_connector *connector, bool force) intel_sdvo_detect(struct drm_connector *connector, bool force)
{ {
@ -1358,10 +1375,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if (edid == NULL) if (edid == NULL)
edid = intel_sdvo_get_analog_edid(connector); edid = intel_sdvo_get_analog_edid(connector);
if (edid != NULL) { if (edid != NULL) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) if (intel_sdvo_connector_matches_edid(intel_sdvo_connector,
ret = connector_status_disconnected; edid))
else
ret = connector_status_connected; ret = connector_status_connected;
else
ret = connector_status_disconnected;
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
kfree(edid); kfree(edid);
} else } else
@ -1402,11 +1421,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
edid = intel_sdvo_get_analog_edid(connector); edid = intel_sdvo_get_analog_edid(connector);
if (edid != NULL) { if (edid != NULL) {
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); edid)) {
bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector);
if (connector_is_digital == monitor_is_digital) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid); drm_add_edid_modes(connector, edid);
} }

View File

@ -405,6 +405,9 @@ int dmar_disabled = 0;
int dmar_disabled = 1; int dmar_disabled = 1;
#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/ #endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
int intel_iommu_enabled = 0;
EXPORT_SYMBOL_GPL(intel_iommu_enabled);
static int dmar_map_gfx = 1; static int dmar_map_gfx = 1;
static int dmar_forcedac; static int dmar_forcedac;
static int intel_iommu_strict; static int intel_iommu_strict;
@ -3647,6 +3650,8 @@ int __init intel_iommu_init(void)
bus_register_notifier(&pci_bus_type, &device_nb); bus_register_notifier(&pci_bus_type, &device_nb);
intel_iommu_enabled = 1;
return 0; return 0;
} }

View File

@ -31,6 +31,7 @@ extern void free_dmar_iommu(struct intel_iommu *iommu);
extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu);
extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
extern int dmar_disabled; extern int dmar_disabled;
extern int intel_iommu_enabled;
#else #else
static inline int iommu_calculate_agaw(struct intel_iommu *iommu) static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
{ {
@ -44,6 +45,7 @@ static inline void free_dmar_iommu(struct intel_iommu *iommu)
{ {
} }
#define dmar_disabled (1) #define dmar_disabled (1)
#define intel_iommu_enabled (0)
#endif #endif