mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
Merge tag 'drm-intel-fixes-2014-06-06' of git://anongit.freedesktop.org/drm-intel into drm-next
> Bunch of stuff for 3.16 still: > - Mipi dsi panel support for byt. Finally! From Shobhit&others. I've > squeezed this in since it's a regression compared to vbios and we've > been ridiculed about it a bit too often ... > - connection_mutex deadlock fix in get_connector (only affects i915). > - Core patches from Matt's primary plane from Matt Roper, I've pushed the > i915 stuff to 3.17. > - vlv power well sequencing fixes from Jesse. > - Fix for cursor size changes from Chris. > - agpbusy fixes from Ville. > - A few smaller things. > * tag 'drm-intel-fixes-2014-06-06' of git://anongit.freedesktop.org/drm-intel: (32 commits) drm/i915: BDW: Adding missing cursor offsets. drm: Fix getconnector connection_mutex locking drm/i915/bdw: Only use 2g GGTT for 32b platforms drm/i915: Nuke pipe A quirk on i830M drm/i915: fix display power sw state reporting drm/i915: Always apply cursor width changes drm/i915: tell the user if both KMS and UMS are disabled drm/plane-helper: Add drm_plane_helper_check_update() (v3) drm: Check CRTC compatibility in setplane drm/i915: use VBT to determine whether to enumerate the VGA port drm/i915: Don't WARN about ring idle bit on gen2 drm/i915: Silence the WARN if the user tries to GTT mmap an incoherent object drm/i915: Move the C3 LP write bit setup to gen3_init_clock_gating() for KMS drm/i915: Enable interrupt-based AGPBUSY# enable on 85x drm/i915: Flip the sense of AGPBUSY_DIS bit drm/i915: Set AGPBUSY# bit in init_clock_gating drm/i915/vlv: add pll assertion when disabling DPIO common well drm/i915/vlv: move DPIO common reset de-assert into __vlv_set_power_well drm/i915/vlv: re-order power wells so DPIO common comes after TX drm/i915/vlv: move CRI refclk enable into __vlv_set_power_well ...
This commit is contained in:
commit
ecb889e620
@ -2178,6 +2178,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check whether this plane is usable on this CRTC */
|
||||
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
|
||||
DRM_DEBUG_KMS("Invalid crtc for plane\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
|
||||
if (!fb) {
|
||||
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
@ -73,6 +74,79 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_helper_check_update() - Check plane update for validity
|
||||
* @plane: plane object to update
|
||||
* @crtc: owning CRTC of owning plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @src: source coordinates in 16.16 fixed point
|
||||
* @dest: integer destination coordinates
|
||||
* @clip: integer clipping coordinates
|
||||
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @can_position: is it legal to position the plane such that it
|
||||
* doesn't cover the entire crtc? This will generally
|
||||
* only be false for primary planes.
|
||||
* @can_update_disabled: can the plane be updated while the crtc
|
||||
* is disabled?
|
||||
* @visible: output parameter indicating whether plane is still visible after
|
||||
* clipping
|
||||
*
|
||||
* Checks that a desired plane update is valid. Drivers that provide
|
||||
* their own plane handling rather than helper-provided implementations may
|
||||
* still wish to call this function to avoid duplication of error checking
|
||||
* code.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero if update appears valid, error code on failure
|
||||
*/
|
||||
int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dest,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
bool can_update_disabled,
|
||||
bool *visible)
|
||||
{
|
||||
int hscale, vscale;
|
||||
|
||||
if (!crtc->enabled && !can_update_disabled) {
|
||||
DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check scaling */
|
||||
hscale = drm_rect_calc_hscale(src, dest, min_scale, max_scale);
|
||||
vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
|
||||
if (hscale < 0 || vscale < 0) {
|
||||
DRM_DEBUG_KMS("Invalid scaling of plane\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
*visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
|
||||
if (!*visible)
|
||||
/*
|
||||
* Plane isn't visible; some drivers can handle this
|
||||
* so we just return success here. Drivers that can't
|
||||
* (including those that use the primary plane helper's
|
||||
* update function) will return an error from their
|
||||
* update_plane handler.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
if (!can_position && !drm_rect_equals(dest, clip)) {
|
||||
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_helper_check_update);
|
||||
|
||||
/**
|
||||
* drm_primary_helper_update() - Helper for primary plane update
|
||||
* @plane: plane object to update
|
||||
@ -121,57 +195,42 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
.x = src_x >> 16,
|
||||
.y = src_y >> 16,
|
||||
};
|
||||
struct drm_rect src = {
|
||||
.x1 = src_x,
|
||||
.y1 = src_y,
|
||||
.x2 = src_x + src_w,
|
||||
.y2 = src_y + src_h,
|
||||
};
|
||||
struct drm_rect dest = {
|
||||
.x1 = crtc_x,
|
||||
.y1 = crtc_y,
|
||||
.x2 = crtc_x + crtc_w,
|
||||
.y2 = crtc_y + crtc_h,
|
||||
};
|
||||
struct drm_rect clip = {
|
||||
const struct drm_rect clip = {
|
||||
.x2 = crtc->mode.hdisplay,
|
||||
.y2 = crtc->mode.vdisplay,
|
||||
};
|
||||
struct drm_connector **connector_list;
|
||||
int num_connectors, ret;
|
||||
bool visible;
|
||||
|
||||
if (!crtc->enabled) {
|
||||
DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disallow subpixel positioning */
|
||||
if ((src_x | src_y | src_w | src_h) & SUBPIXEL_MASK) {
|
||||
DRM_DEBUG_KMS("Primary plane does not support subpixel positioning\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Primary planes are locked to their owning CRTC */
|
||||
if (plane->possible_crtcs != drm_crtc_mask(crtc)) {
|
||||
DRM_DEBUG_KMS("Cannot change primary plane CRTC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disallow scaling */
|
||||
src_w >>= 16;
|
||||
src_h >>= 16;
|
||||
if (crtc_w != src_w || crtc_h != src_h) {
|
||||
DRM_DEBUG_KMS("Can't scale primary plane\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Make sure primary plane covers entire CRTC */
|
||||
drm_rect_intersect(&dest, &clip);
|
||||
if (dest.x1 != 0 || dest.y1 != 0 ||
|
||||
dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) {
|
||||
DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Framebuffer must be big enough to cover entire plane */
|
||||
ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb);
|
||||
ret = drm_plane_helper_check_update(plane, crtc, fb,
|
||||
&src, &dest, &clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, false, &visible);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!visible)
|
||||
/*
|
||||
* Primary plane isn't visible. Note that unless a driver
|
||||
* provides their own disable function, this will just
|
||||
* wind up returning -EINVAL to userspace.
|
||||
*/
|
||||
return plane->funcs->disable_plane(plane);
|
||||
|
||||
/* Find current connectors for CRTC */
|
||||
num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
|
||||
BUG_ON(num_connectors == 0);
|
||||
|
@ -62,6 +62,7 @@ i915-y += dvo_ch7017.o \
|
||||
intel_dsi_cmd.o \
|
||||
intel_dsi.o \
|
||||
intel_dsi_pll.o \
|
||||
intel_dsi_panel_vbt.o \
|
||||
intel_dvo.o \
|
||||
intel_hdmi.o \
|
||||
intel_i2c.o \
|
||||
|
@ -2353,10 +2353,14 @@ static int i915_display_info(struct seq_file *m, void *unused)
|
||||
|
||||
active = cursor_position(dev, crtc->pipe, &x, &y);
|
||||
seq_printf(m, "\tcursor visible? %s, position (%d, %d), addr 0x%08x, active? %s\n",
|
||||
yesno(crtc->cursor_visible),
|
||||
yesno(crtc->cursor_base),
|
||||
x, y, crtc->cursor_addr,
|
||||
yesno(active));
|
||||
}
|
||||
|
||||
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
|
||||
yesno(!crtc->cpu_fifo_underrun_disabled),
|
||||
yesno(!crtc->pch_fifo_underrun_disabled));
|
||||
}
|
||||
|
||||
seq_printf(m, "\n");
|
||||
|
@ -321,6 +321,7 @@ static const struct intel_device_info intel_broadwell_m_info = {
|
||||
.has_ddi = 1,
|
||||
.has_fbc = 1,
|
||||
GEN_DEFAULT_PIPEOFFSETS,
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_broadwell_gt3d_info = {
|
||||
@ -331,6 +332,7 @@ static const struct intel_device_info intel_broadwell_gt3d_info = {
|
||||
.has_ddi = 1,
|
||||
.has_fbc = 1,
|
||||
GEN_DEFAULT_PIPEOFFSETS,
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_broadwell_gt3m_info = {
|
||||
@ -811,17 +813,17 @@ int i915_reset(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is horribly race against concurrent pageflip and
|
||||
* vblank wait ioctls since they can observe dev->irqs_disabled
|
||||
* being false when they shouldn't be able to.
|
||||
* FIXME: This races pretty badly against concurrent holders of
|
||||
* ring interrupts. This is possible since we've started to drop
|
||||
* dev->struct_mutex in select places when waiting for the gpu.
|
||||
*/
|
||||
drm_irq_uninstall(dev);
|
||||
drm_irq_install(dev, dev->pdev->irq);
|
||||
|
||||
/* rps/rc6 re-init is necessary to restore state lost after the
|
||||
* reset and the re-install of drm irq. Skip for ironlake per
|
||||
/*
|
||||
* rps/rc6 re-init is necessary to restore state lost after the
|
||||
* reset and the re-install of gt irqs. Skip for ironlake per
|
||||
* previous concerns that it doesn't respond well to some forms
|
||||
* of re-init after reset. */
|
||||
* of re-init after reset.
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen > 5)
|
||||
intel_reset_gt_powersave(dev);
|
||||
|
||||
@ -1583,6 +1585,7 @@ static int __init i915_init(void)
|
||||
driver.get_vblank_timestamp = NULL;
|
||||
#ifndef CONFIG_DRM_I915_UMS
|
||||
/* Silently fail loading to not upset userspace. */
|
||||
DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -1207,6 +1207,7 @@ struct intel_vbt_data {
|
||||
unsigned int lvds_use_ssc:1;
|
||||
unsigned int display_clock_mode:1;
|
||||
unsigned int fdi_rx_polarity_inverted:1;
|
||||
unsigned int has_mipi:1;
|
||||
int lvds_ssc_freq;
|
||||
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
|
||||
|
||||
@ -1230,6 +1231,7 @@ struct intel_vbt_data {
|
||||
|
||||
/* MIPI DSI */
|
||||
struct {
|
||||
u16 port;
|
||||
u16 panel_id;
|
||||
struct mipi_config *config;
|
||||
struct mipi_pps_data *pps;
|
||||
|
@ -1544,7 +1544,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
|
||||
/* Access to snoopable pages through the GTT is incoherent. */
|
||||
if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
|
||||
ret = -EINVAL;
|
||||
ret = -EFAULT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@ -4894,7 +4894,7 @@ i915_gem_load(struct drm_device *dev)
|
||||
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
|
||||
|
||||
/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
|
||||
if (IS_GEN3(dev)) {
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET) && IS_GEN3(dev)) {
|
||||
I915_WRITE(MI_ARB_STATE,
|
||||
_MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
|
||||
}
|
||||
|
@ -1775,6 +1775,13 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
|
||||
bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
|
||||
if (bdw_gmch_ctl)
|
||||
bdw_gmch_ctl = 1 << bdw_gmch_ctl;
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */
|
||||
if (bdw_gmch_ctl > 4)
|
||||
bdw_gmch_ctl = 4;
|
||||
#endif
|
||||
|
||||
return bdw_gmch_ctl << 20;
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,8 @@ void i9xx_check_fifo_underruns(struct drm_device *dev)
|
||||
}
|
||||
|
||||
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
enum pipe pipe, bool enable)
|
||||
enum pipe pipe,
|
||||
bool enable, bool old)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg = PIPESTAT(pipe);
|
||||
@ -347,7 +348,7 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
|
||||
POSTING_READ(reg);
|
||||
} else {
|
||||
if (pipestat & PIPE_FIFO_UNDERRUN_STATUS)
|
||||
if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
|
||||
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
|
||||
}
|
||||
}
|
||||
@ -366,7 +367,8 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
}
|
||||
|
||||
static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
enum pipe pipe, bool enable)
|
||||
enum pipe pipe,
|
||||
bool enable, bool old)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
if (enable) {
|
||||
@ -379,7 +381,8 @@ static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
} else {
|
||||
ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
|
||||
|
||||
if (I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
|
||||
if (old &&
|
||||
I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
|
||||
DRM_ERROR("uncleared fifo underrun on pipe %c\n",
|
||||
pipe_name(pipe));
|
||||
}
|
||||
@ -444,7 +447,7 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
|
||||
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
enum transcoder pch_transcoder,
|
||||
bool enable)
|
||||
bool enable, bool old)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
@ -459,7 +462,8 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
} else {
|
||||
ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
|
||||
|
||||
if (I915_READ(SERR_INT) & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
|
||||
if (old && I915_READ(SERR_INT) &
|
||||
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
|
||||
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
|
||||
transcoder_name(pch_transcoder));
|
||||
}
|
||||
@ -486,28 +490,23 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
|
||||
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);
|
||||
bool ret;
|
||||
bool old;
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
||||
ret = !intel_crtc->cpu_fifo_underrun_disabled;
|
||||
|
||||
if (enable == ret)
|
||||
goto done;
|
||||
|
||||
old = !intel_crtc->cpu_fifo_underrun_disabled;
|
||||
intel_crtc->cpu_fifo_underrun_disabled = !enable;
|
||||
|
||||
if (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
|
||||
i9xx_set_fifo_underrun_reporting(dev, pipe, enable);
|
||||
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
|
||||
else if (IS_GEN5(dev) || IS_GEN6(dev))
|
||||
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
|
||||
else if (IS_GEN7(dev))
|
||||
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
|
||||
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
|
||||
else if (IS_GEN8(dev))
|
||||
broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
|
||||
@ -556,7 +555,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
|
||||
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
unsigned long flags;
|
||||
bool ret;
|
||||
bool old;
|
||||
|
||||
/*
|
||||
* NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
|
||||
@ -569,21 +568,16 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, flags);
|
||||
|
||||
ret = !intel_crtc->pch_fifo_underrun_disabled;
|
||||
|
||||
if (enable == ret)
|
||||
goto done;
|
||||
|
||||
old = !intel_crtc->pch_fifo_underrun_disabled;
|
||||
intel_crtc->pch_fifo_underrun_disabled = !enable;
|
||||
|
||||
if (HAS_PCH_IBX(dev))
|
||||
ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
|
||||
else
|
||||
cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
|
||||
cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable, old);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
|
||||
return ret;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
@ -2634,10 +2628,6 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
|
||||
else
|
||||
i915_enable_pipestat(dev_priv, pipe,
|
||||
PIPE_VBLANK_INTERRUPT_STATUS);
|
||||
|
||||
/* maintain vblank delivery even in deep C-states */
|
||||
if (INTEL_INFO(dev)->gen == 3)
|
||||
I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
|
||||
return 0;
|
||||
@ -2701,9 +2691,6 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
if (INTEL_INFO(dev)->gen == 3)
|
||||
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
|
||||
|
||||
i915_disable_pipestat(dev_priv, pipe,
|
||||
PIPE_VBLANK_INTERRUPT_STATUS |
|
||||
PIPE_START_VBLANK_INTERRUPT_STATUS);
|
||||
@ -3117,11 +3104,6 @@ static void ironlake_irq_reset(struct drm_device *dev)
|
||||
ibx_irq_reset(dev);
|
||||
}
|
||||
|
||||
static void ironlake_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
ironlake_irq_reset(dev);
|
||||
}
|
||||
|
||||
static void valleyview_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@ -3151,6 +3133,14 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
|
||||
POSTING_READ(VLV_IER);
|
||||
}
|
||||
|
||||
static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
GEN8_IRQ_RESET_NDX(GT, 0);
|
||||
GEN8_IRQ_RESET_NDX(GT, 1);
|
||||
GEN8_IRQ_RESET_NDX(GT, 2);
|
||||
GEN8_IRQ_RESET_NDX(GT, 3);
|
||||
}
|
||||
|
||||
static void gen8_irq_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@ -3159,10 +3149,7 @@ static void gen8_irq_reset(struct drm_device *dev)
|
||||
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
|
||||
GEN8_IRQ_RESET_NDX(GT, 0);
|
||||
GEN8_IRQ_RESET_NDX(GT, 1);
|
||||
GEN8_IRQ_RESET_NDX(GT, 2);
|
||||
GEN8_IRQ_RESET_NDX(GT, 3);
|
||||
gen8_gt_irq_reset(dev_priv);
|
||||
|
||||
for_each_pipe(pipe)
|
||||
GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
|
||||
@ -3174,11 +3161,6 @@ static void gen8_irq_reset(struct drm_device *dev)
|
||||
ibx_irq_reset(dev);
|
||||
}
|
||||
|
||||
static void gen8_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
gen8_irq_reset(dev);
|
||||
}
|
||||
|
||||
static void cherryview_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@ -3187,10 +3169,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
|
||||
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
|
||||
GEN8_IRQ_RESET_NDX(GT, 0);
|
||||
GEN8_IRQ_RESET_NDX(GT, 1);
|
||||
GEN8_IRQ_RESET_NDX(GT, 2);
|
||||
GEN8_IRQ_RESET_NDX(GT, 3);
|
||||
gen8_gt_irq_reset(dev_priv);
|
||||
|
||||
GEN5_IRQ_RESET(GEN8_PCU_);
|
||||
|
||||
@ -4387,7 +4366,7 @@ void intel_irq_init(struct drm_device *dev)
|
||||
dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
|
||||
} else if (IS_GEN8(dev)) {
|
||||
dev->driver->irq_handler = gen8_irq_handler;
|
||||
dev->driver->irq_preinstall = gen8_irq_preinstall;
|
||||
dev->driver->irq_preinstall = gen8_irq_reset;
|
||||
dev->driver->irq_postinstall = gen8_irq_postinstall;
|
||||
dev->driver->irq_uninstall = gen8_irq_uninstall;
|
||||
dev->driver->enable_vblank = gen8_enable_vblank;
|
||||
@ -4395,7 +4374,7 @@ void intel_irq_init(struct drm_device *dev)
|
||||
dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
|
||||
} else if (HAS_PCH_SPLIT(dev)) {
|
||||
dev->driver->irq_handler = ironlake_irq_handler;
|
||||
dev->driver->irq_preinstall = ironlake_irq_preinstall;
|
||||
dev->driver->irq_preinstall = ironlake_irq_reset;
|
||||
dev->driver->irq_postinstall = ironlake_irq_postinstall;
|
||||
dev->driver->irq_uninstall = ironlake_irq_uninstall;
|
||||
dev->driver->enable_vblank = ironlake_enable_vblank;
|
||||
|
@ -1179,7 +1179,7 @@ enum punit_power_well {
|
||||
#define I915_ERROR_INSTRUCTION (1<<0)
|
||||
#define INSTPM 0x020c0
|
||||
#define INSTPM_SELF_EN (1<<12) /* 915GM only */
|
||||
#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts
|
||||
#define INSTPM_AGPBUSY_INT_EN (1<<11) /* gen3: when disabled, pending interrupts
|
||||
will not assert AGPBUSY# and will only
|
||||
be delivered when out of C3. */
|
||||
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
|
||||
@ -1260,6 +1260,10 @@ enum punit_power_well {
|
||||
#define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */
|
||||
#define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */
|
||||
|
||||
#define MI_STATE 0x020e4 /* gen2 only */
|
||||
#define MI_AGPBUSY_INT_EN (1 << 1) /* 85x only */
|
||||
#define MI_AGPBUSY_830_MODE (1 << 0) /* 85x only */
|
||||
|
||||
#define CACHE_MODE_0 0x02120 /* 915+ only */
|
||||
#define CM0_PIPELINED_RENDER_FLUSH_DISABLE (1<<8)
|
||||
#define CM0_IZ_OPT_DISABLE (1<<6)
|
||||
|
@ -744,6 +744,10 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||
int i, panel_id, seq_size;
|
||||
u16 block_size;
|
||||
|
||||
/* parse MIPI blocks only if LFP type is MIPI */
|
||||
if (!dev_priv->vbt.has_mipi)
|
||||
return;
|
||||
|
||||
/* Initialize this to undefined indicating no generic MIPI support */
|
||||
dev_priv->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
|
||||
|
||||
@ -1059,6 +1063,15 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
||||
/* skip the device block if device type is invalid */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p_child->common.dvo_port >= DVO_PORT_MIPIA
|
||||
&& p_child->common.dvo_port <= DVO_PORT_MIPID
|
||||
&&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) {
|
||||
DRM_DEBUG_KMS("Found MIPI as LFP\n");
|
||||
dev_priv->vbt.has_mipi = 1;
|
||||
dev_priv->vbt.dsi.port = p_child->common.dvo_port;
|
||||
}
|
||||
|
||||
child_dev_ptr = dev_priv->vbt.child_dev + count;
|
||||
count++;
|
||||
memcpy((void *)child_dev_ptr, (void *)p_child,
|
||||
|
@ -743,6 +743,10 @@ int intel_parse_bios(struct drm_device *dev);
|
||||
#define DVO_PORT_DPC 8
|
||||
#define DVO_PORT_DPD 9
|
||||
#define DVO_PORT_DPA 10
|
||||
#define DVO_PORT_MIPIA 21
|
||||
#define DVO_PORT_MIPIB 22
|
||||
#define DVO_PORT_MIPIC 23
|
||||
#define DVO_PORT_MIPID 24
|
||||
|
||||
/* Block 52 contains MIPI Panel info
|
||||
* 6 such enteries will there. Index into correct
|
||||
|
@ -1484,14 +1484,6 @@ static void intel_reset_dpio(struct drm_device *dev)
|
||||
if (!IS_VALLEYVIEW(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Enable the CRI clock source so we can get at the display and the
|
||||
* reference clock for VGA hotplug / manual detection.
|
||||
*/
|
||||
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
|
||||
DPLL_REFA_CLK_ENABLE_VLV |
|
||||
DPLL_INTEGRATED_CRI_CLK_VLV);
|
||||
|
||||
if (IS_CHERRYVIEW(dev)) {
|
||||
enum dpio_phy phy;
|
||||
u32 val;
|
||||
@ -1516,17 +1508,23 @@ static void intel_reset_dpio(struct drm_device *dev)
|
||||
|
||||
} else {
|
||||
/*
|
||||
* From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
|
||||
* 6. De-assert cmn_reset/side_reset. Same as VLV X0.
|
||||
* a. GUnit 0x2110 bit[0] set to 1 (def 0)
|
||||
* b. The other bits such as sfr settings / modesel may all
|
||||
* be set to 0.
|
||||
*
|
||||
* This should only be done on init and resume from S3 with
|
||||
* both PLLs disabled, or we risk losing DPIO and PLL
|
||||
* synchronization.
|
||||
* If DPIO has already been reset, e.g. by BIOS, just skip all
|
||||
* this.
|
||||
*/
|
||||
I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
|
||||
if (I915_READ(DPIO_CTL) & DPIO_CMNRST)
|
||||
return;
|
||||
|
||||
/*
|
||||
* From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
|
||||
* Need to assert and de-assert PHY SB reset by gating the
|
||||
* common lane power, then un-gating it.
|
||||
* Simply ungating isn't enough to reset the PHY enough to get
|
||||
* ports and lanes running.
|
||||
*/
|
||||
__vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
|
||||
false);
|
||||
__vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7868,29 +7866,33 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
bool visible = base != 0;
|
||||
u32 cntl;
|
||||
uint32_t cntl;
|
||||
|
||||
if (intel_crtc->cursor_visible == visible)
|
||||
return;
|
||||
|
||||
cntl = I915_READ(_CURACNTR);
|
||||
if (visible) {
|
||||
if (base != intel_crtc->cursor_base) {
|
||||
/* On these chipsets we can only modify the base whilst
|
||||
* the cursor is disabled.
|
||||
*/
|
||||
if (intel_crtc->cursor_cntl) {
|
||||
I915_WRITE(_CURACNTR, 0);
|
||||
POSTING_READ(_CURACNTR);
|
||||
intel_crtc->cursor_cntl = 0;
|
||||
}
|
||||
|
||||
I915_WRITE(_CURABASE, base);
|
||||
POSTING_READ(_CURABASE);
|
||||
}
|
||||
|
||||
cntl &= ~(CURSOR_FORMAT_MASK);
|
||||
/* XXX width must be 64, stride 256 => 0x00 << 28 */
|
||||
cntl |= CURSOR_ENABLE |
|
||||
/* XXX width must be 64, stride 256 => 0x00 << 28 */
|
||||
cntl = 0;
|
||||
if (base)
|
||||
cntl = (CURSOR_ENABLE |
|
||||
CURSOR_GAMMA_ENABLE |
|
||||
CURSOR_FORMAT_ARGB;
|
||||
} else
|
||||
cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
|
||||
I915_WRITE(_CURACNTR, cntl);
|
||||
|
||||
intel_crtc->cursor_visible = visible;
|
||||
CURSOR_FORMAT_ARGB);
|
||||
if (intel_crtc->cursor_cntl != cntl) {
|
||||
I915_WRITE(_CURACNTR, cntl);
|
||||
POSTING_READ(_CURACNTR);
|
||||
intel_crtc->cursor_cntl = cntl;
|
||||
}
|
||||
}
|
||||
|
||||
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
@ -7899,16 +7901,12 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
bool visible = base != 0;
|
||||
uint32_t cntl;
|
||||
|
||||
if (intel_crtc->cursor_visible != visible) {
|
||||
int16_t width = intel_crtc->cursor_width;
|
||||
uint32_t cntl = I915_READ(CURCNTR(pipe));
|
||||
if (base) {
|
||||
cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
|
||||
cntl |= MCURSOR_GAMMA_ENABLE;
|
||||
|
||||
switch (width) {
|
||||
cntl = 0;
|
||||
if (base) {
|
||||
cntl = MCURSOR_GAMMA_ENABLE;
|
||||
switch (intel_crtc->cursor_width) {
|
||||
case 64:
|
||||
cntl |= CURSOR_MODE_64_ARGB_AX;
|
||||
break;
|
||||
@ -7921,18 +7919,16 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
cntl |= pipe << 28; /* Connect to correct pipe */
|
||||
} else {
|
||||
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
|
||||
cntl |= CURSOR_MODE_DISABLE;
|
||||
}
|
||||
I915_WRITE(CURCNTR(pipe), cntl);
|
||||
|
||||
intel_crtc->cursor_visible = visible;
|
||||
cntl |= pipe << 28; /* Connect to correct pipe */
|
||||
}
|
||||
if (intel_crtc->cursor_cntl != cntl) {
|
||||
I915_WRITE(CURCNTR(pipe), cntl);
|
||||
POSTING_READ(CURCNTR(pipe));
|
||||
intel_crtc->cursor_cntl = cntl;
|
||||
}
|
||||
|
||||
/* and commit changes on next vblank */
|
||||
POSTING_READ(CURCNTR(pipe));
|
||||
I915_WRITE(CURBASE(pipe), base);
|
||||
POSTING_READ(CURBASE(pipe));
|
||||
}
|
||||
@ -7943,15 +7939,12 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
bool visible = base != 0;
|
||||
uint32_t cntl;
|
||||
|
||||
if (intel_crtc->cursor_visible != visible) {
|
||||
int16_t width = intel_crtc->cursor_width;
|
||||
uint32_t cntl = I915_READ(CURCNTR(pipe));
|
||||
if (base) {
|
||||
cntl &= ~CURSOR_MODE;
|
||||
cntl |= MCURSOR_GAMMA_ENABLE;
|
||||
switch (width) {
|
||||
cntl = 0;
|
||||
if (base) {
|
||||
cntl = MCURSOR_GAMMA_ENABLE;
|
||||
switch (intel_crtc->cursor_width) {
|
||||
case 64:
|
||||
cntl |= CURSOR_MODE_64_ARGB_AX;
|
||||
break;
|
||||
@ -7964,21 +7957,18 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
|
||||
cntl |= CURSOR_MODE_DISABLE;
|
||||
}
|
||||
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
||||
cntl |= CURSOR_PIPE_CSC_ENABLE;
|
||||
cntl &= ~CURSOR_TRICKLE_FEED_DISABLE;
|
||||
}
|
||||
I915_WRITE(CURCNTR(pipe), cntl);
|
||||
|
||||
intel_crtc->cursor_visible = visible;
|
||||
}
|
||||
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
cntl |= CURSOR_PIPE_CSC_ENABLE;
|
||||
|
||||
if (intel_crtc->cursor_cntl != cntl) {
|
||||
I915_WRITE(CURCNTR(pipe), cntl);
|
||||
POSTING_READ(CURCNTR(pipe));
|
||||
intel_crtc->cursor_cntl = cntl;
|
||||
}
|
||||
|
||||
/* and commit changes on next vblank */
|
||||
POSTING_READ(CURCNTR(pipe));
|
||||
I915_WRITE(CURBASE(pipe), base);
|
||||
POSTING_READ(CURBASE(pipe));
|
||||
}
|
||||
@ -7994,7 +7984,6 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
||||
int x = intel_crtc->cursor_x;
|
||||
int y = intel_crtc->cursor_y;
|
||||
u32 base = 0, pos = 0;
|
||||
bool visible;
|
||||
|
||||
if (on)
|
||||
base = intel_crtc->cursor_addr;
|
||||
@ -8023,8 +8012,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
||||
}
|
||||
pos |= y << CURSOR_Y_SHIFT;
|
||||
|
||||
visible = base != 0;
|
||||
if (!visible && !intel_crtc->cursor_visible)
|
||||
if (base == 0 && intel_crtc->cursor_base == 0)
|
||||
return;
|
||||
|
||||
I915_WRITE(CURPOS(pipe), pos);
|
||||
@ -8035,6 +8023,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
||||
i845_update_cursor(crtc, base);
|
||||
else
|
||||
i9xx_update_cursor(crtc, base);
|
||||
intel_crtc->cursor_base = base;
|
||||
}
|
||||
|
||||
static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
@ -10990,6 +10979,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
||||
intel_crtc->plane = !pipe;
|
||||
}
|
||||
|
||||
intel_crtc->cursor_base = ~0;
|
||||
intel_crtc->cursor_cntl = ~0;
|
||||
|
||||
init_waitqueue_head(&intel_crtc->vbl_wait);
|
||||
|
||||
BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
|
||||
@ -11103,7 +11095,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
|
||||
intel_lvds_init(dev);
|
||||
|
||||
if (!IS_ULT(dev) && !IS_CHERRYVIEW(dev))
|
||||
if (!IS_ULT(dev) && !IS_CHERRYVIEW(dev) && dev_priv->vbt.int_crt_support)
|
||||
intel_crt_init(dev);
|
||||
|
||||
if (HAS_DDI(dev)) {
|
||||
@ -11618,9 +11610,6 @@ static struct intel_quirk intel_quirks[] = {
|
||||
/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
|
||||
{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
|
||||
|
||||
/* 830 needs to leave pipe A & dpll A up */
|
||||
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
|
||||
|
||||
/* Lenovo U160 cannot use SSC on LVDS */
|
||||
{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
|
||||
|
||||
|
@ -386,7 +386,8 @@ struct intel_crtc {
|
||||
uint32_t cursor_addr;
|
||||
int16_t cursor_x, cursor_y;
|
||||
int16_t cursor_width, cursor_height;
|
||||
bool cursor_visible;
|
||||
uint32_t cursor_cntl;
|
||||
uint32_t cursor_base;
|
||||
|
||||
struct intel_plane_config plane_config;
|
||||
struct intel_crtc_config config;
|
||||
@ -973,7 +974,8 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
|
||||
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
|
||||
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
|
||||
void ilk_wm_get_hw_state(struct drm_device *dev);
|
||||
|
||||
void __vlv_set_power_well(struct drm_i915_private *dev_priv,
|
||||
enum punit_power_well power_well_id, bool enable);
|
||||
|
||||
/* intel_sdvo.c */
|
||||
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
|
||||
|
@ -35,6 +35,11 @@
|
||||
|
||||
/* the sub-encoders aka panel drivers */
|
||||
static const struct intel_dsi_device intel_dsi_devices[] = {
|
||||
{
|
||||
.panel_id = MIPI_DSI_GENERIC_PANEL_ID,
|
||||
.name = "vbt-generic-dsi-vid-mode-display",
|
||||
.dev_ops = &vbt_generic_dsi_display_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static void band_gap_reset(struct drm_i915_private *dev_priv)
|
||||
@ -201,6 +206,19 @@ static void intel_dsi_enable_nop(struct intel_encoder *encoder)
|
||||
*/
|
||||
}
|
||||
|
||||
static void intel_dsi_pre_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (is_vid_mode(intel_dsi)) {
|
||||
/* Send Shutdown command to the panel in LP mode */
|
||||
dpi_send_cmd(intel_dsi, SHUTDOWN, DPI_LP_MODE_EN);
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_dsi_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
@ -213,10 +231,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (is_vid_mode(intel_dsi)) {
|
||||
/* Send Shutdown command to the panel in LP mode */
|
||||
dpi_send_cmd(intel_dsi, SHUTDOWN, DPI_LP_MODE_EN);
|
||||
msleep(10);
|
||||
|
||||
/* de-assert ip_tg_enable signal */
|
||||
temp = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||
I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE);
|
||||
@ -288,6 +302,8 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder)
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
intel_dsi_disable(encoder);
|
||||
|
||||
intel_dsi_clear_device_ready(encoder);
|
||||
|
||||
val = I915_READ(DSPCLK_GATE_D);
|
||||
@ -655,6 +671,10 @@ bool intel_dsi_init(struct drm_device *dev)
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
/* There is no detection method for MIPI so rely on VBT */
|
||||
if (!dev_priv->vbt.has_mipi)
|
||||
return false;
|
||||
|
||||
intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
|
||||
if (!intel_dsi)
|
||||
return false;
|
||||
@ -686,7 +706,7 @@ bool intel_dsi_init(struct drm_device *dev)
|
||||
intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable;
|
||||
intel_encoder->pre_enable = intel_dsi_pre_enable;
|
||||
intel_encoder->enable = intel_dsi_enable_nop;
|
||||
intel_encoder->disable = intel_dsi_disable;
|
||||
intel_encoder->disable = intel_dsi_pre_disable;
|
||||
intel_encoder->post_disable = intel_dsi_post_disable;
|
||||
intel_encoder->get_hw_state = intel_dsi_get_hw_state;
|
||||
intel_encoder->get_config = intel_dsi_get_config;
|
||||
|
@ -133,4 +133,6 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
|
||||
extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
|
||||
extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
|
||||
|
||||
extern struct intel_dsi_dev_ops vbt_generic_dsi_display_ops;
|
||||
|
||||
#endif /* _INTEL_DSI_H */
|
||||
|
589
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
Normal file
589
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
Normal file
@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Copyright © 2014 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.
|
||||
*
|
||||
* Author: Shobhit Kumar <shobhit.kumar@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <video/mipi_display.h>
|
||||
#include <asm/intel-mid.h>
|
||||
#include <video/mipi_display.h>
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_dsi_cmd.h"
|
||||
|
||||
#define MIPI_TRANSFER_MODE_SHIFT 0
|
||||
#define MIPI_VIRTUAL_CHANNEL_SHIFT 1
|
||||
#define MIPI_PORT_SHIFT 3
|
||||
|
||||
#define PREPARE_CNT_MAX 0x3F
|
||||
#define EXIT_ZERO_CNT_MAX 0x3F
|
||||
#define CLK_ZERO_CNT_MAX 0xFF
|
||||
#define TRAIL_CNT_MAX 0x1F
|
||||
|
||||
#define NS_KHZ_RATIO 1000000
|
||||
|
||||
#define GPI0_NC_0_HV_DDI0_HPD 0x4130
|
||||
#define GPIO_NC_0_HV_DDI0_PAD 0x4138
|
||||
#define GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120
|
||||
#define GPIO_NC_1_HV_DDI0_DDC_SDA_PAD 0x4128
|
||||
#define GPIO_NC_2_HV_DDI0_DDC_SCL 0x4110
|
||||
#define GPIO_NC_2_HV_DDI0_DDC_SCL_PAD 0x4118
|
||||
#define GPIO_NC_3_PANEL0_VDDEN 0x4140
|
||||
#define GPIO_NC_3_PANEL0_VDDEN_PAD 0x4148
|
||||
#define GPIO_NC_4_PANEL0_BLKEN 0x4150
|
||||
#define GPIO_NC_4_PANEL0_BLKEN_PAD 0x4158
|
||||
#define GPIO_NC_5_PANEL0_BLKCTL 0x4160
|
||||
#define GPIO_NC_5_PANEL0_BLKCTL_PAD 0x4168
|
||||
#define GPIO_NC_6_PCONF0 0x4180
|
||||
#define GPIO_NC_6_PAD 0x4188
|
||||
#define GPIO_NC_7_PCONF0 0x4190
|
||||
#define GPIO_NC_7_PAD 0x4198
|
||||
#define GPIO_NC_8_PCONF0 0x4170
|
||||
#define GPIO_NC_8_PAD 0x4178
|
||||
#define GPIO_NC_9_PCONF0 0x4100
|
||||
#define GPIO_NC_9_PAD 0x4108
|
||||
#define GPIO_NC_10_PCONF0 0x40E0
|
||||
#define GPIO_NC_10_PAD 0x40E8
|
||||
#define GPIO_NC_11_PCONF0 0x40F0
|
||||
#define GPIO_NC_11_PAD 0x40F8
|
||||
|
||||
struct gpio_table {
|
||||
u16 function_reg;
|
||||
u16 pad_reg;
|
||||
u8 init;
|
||||
};
|
||||
|
||||
static struct gpio_table gtable[] = {
|
||||
{ GPI0_NC_0_HV_DDI0_HPD, GPIO_NC_0_HV_DDI0_PAD, 0 },
|
||||
{ GPIO_NC_1_HV_DDI0_DDC_SDA, GPIO_NC_1_HV_DDI0_DDC_SDA_PAD, 0 },
|
||||
{ GPIO_NC_2_HV_DDI0_DDC_SCL, GPIO_NC_2_HV_DDI0_DDC_SCL_PAD, 0 },
|
||||
{ GPIO_NC_3_PANEL0_VDDEN, GPIO_NC_3_PANEL0_VDDEN_PAD, 0 },
|
||||
{ GPIO_NC_4_PANEL0_BLKEN, GPIO_NC_4_PANEL0_BLKEN_PAD, 0 },
|
||||
{ GPIO_NC_5_PANEL0_BLKCTL, GPIO_NC_5_PANEL0_BLKCTL_PAD, 0 },
|
||||
{ GPIO_NC_6_PCONF0, GPIO_NC_6_PAD, 0 },
|
||||
{ GPIO_NC_7_PCONF0, GPIO_NC_7_PAD, 0 },
|
||||
{ GPIO_NC_8_PCONF0, GPIO_NC_8_PAD, 0 },
|
||||
{ GPIO_NC_9_PCONF0, GPIO_NC_9_PAD, 0 },
|
||||
{ GPIO_NC_10_PCONF0, GPIO_NC_10_PAD, 0},
|
||||
{ GPIO_NC_11_PCONF0, GPIO_NC_11_PAD, 0}
|
||||
};
|
||||
|
||||
static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data)
|
||||
{
|
||||
u8 type, byte, mode, vc, port;
|
||||
u16 len;
|
||||
|
||||
byte = *data++;
|
||||
mode = (byte >> MIPI_TRANSFER_MODE_SHIFT) & 0x1;
|
||||
vc = (byte >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 0x3;
|
||||
port = (byte >> MIPI_PORT_SHIFT) & 0x3;
|
||||
|
||||
/* LP or HS mode */
|
||||
intel_dsi->hs = mode;
|
||||
|
||||
/* get packet type and increment the pointer */
|
||||
type = *data++;
|
||||
|
||||
len = *((u16 *) data);
|
||||
data += 2;
|
||||
|
||||
switch (type) {
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
|
||||
dsi_vc_generic_write_0(intel_dsi, vc);
|
||||
break;
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
|
||||
dsi_vc_generic_write_1(intel_dsi, vc, *data);
|
||||
break;
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
|
||||
dsi_vc_generic_write_2(intel_dsi, vc, *data, *(data + 1));
|
||||
break;
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
|
||||
case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
|
||||
DRM_DEBUG_DRIVER("Generic Read not yet implemented or used\n");
|
||||
break;
|
||||
case MIPI_DSI_GENERIC_LONG_WRITE:
|
||||
dsi_vc_generic_write(intel_dsi, vc, data, len);
|
||||
break;
|
||||
case MIPI_DSI_DCS_SHORT_WRITE:
|
||||
dsi_vc_dcs_write_0(intel_dsi, vc, *data);
|
||||
break;
|
||||
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
|
||||
dsi_vc_dcs_write_1(intel_dsi, vc, *data, *(data + 1));
|
||||
break;
|
||||
case MIPI_DSI_DCS_READ:
|
||||
DRM_DEBUG_DRIVER("DCS Read not yet implemented or used\n");
|
||||
break;
|
||||
case MIPI_DSI_DCS_LONG_WRITE:
|
||||
dsi_vc_dcs_write(intel_dsi, vc, data, len);
|
||||
break;
|
||||
};
|
||||
|
||||
data += len;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, u8 *data)
|
||||
{
|
||||
u32 delay = *((u32 *) data);
|
||||
|
||||
usleep_range(delay, delay + 10);
|
||||
data += 4;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, u8 *data)
|
||||
{
|
||||
u8 gpio, action;
|
||||
u16 function, pad;
|
||||
u32 val;
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
gpio = *data++;
|
||||
|
||||
/* pull up/down */
|
||||
action = *data++;
|
||||
|
||||
function = gtable[gpio].function_reg;
|
||||
pad = gtable[gpio].pad_reg;
|
||||
|
||||
mutex_lock(&dev_priv->dpio_lock);
|
||||
if (!gtable[gpio].init) {
|
||||
/* program the function */
|
||||
/* FIXME: remove constant below */
|
||||
vlv_gpio_nc_write(dev_priv, function, 0x2000CC00);
|
||||
gtable[gpio].init = 1;
|
||||
}
|
||||
|
||||
val = 0x4 | action;
|
||||
|
||||
/* pull up/down */
|
||||
vlv_gpio_nc_write(dev_priv, pad, val);
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
typedef u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, u8 *data);
|
||||
static const fn_mipi_elem_exec exec_elem[] = {
|
||||
NULL, /* reserved */
|
||||
mipi_exec_send_packet,
|
||||
mipi_exec_delay,
|
||||
mipi_exec_gpio,
|
||||
NULL, /* status read; later */
|
||||
};
|
||||
|
||||
/*
|
||||
* MIPI Sequence from VBT #53 parsing logic
|
||||
* We have already separated each seqence during bios parsing
|
||||
* Following is generic execution function for any sequence
|
||||
*/
|
||||
|
||||
static const char * const seq_name[] = {
|
||||
"UNDEFINED",
|
||||
"MIPI_SEQ_ASSERT_RESET",
|
||||
"MIPI_SEQ_INIT_OTP",
|
||||
"MIPI_SEQ_DISPLAY_ON",
|
||||
"MIPI_SEQ_DISPLAY_OFF",
|
||||
"MIPI_SEQ_DEASSERT_RESET"
|
||||
};
|
||||
|
||||
static void generic_exec_sequence(struct intel_dsi *intel_dsi, char *sequence)
|
||||
{
|
||||
u8 *data = sequence;
|
||||
fn_mipi_elem_exec mipi_elem_exec;
|
||||
int index;
|
||||
|
||||
if (!sequence)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_DRIVER("Starting MIPI sequence - %s\n", seq_name[*data]);
|
||||
|
||||
/* go to the first element of the sequence */
|
||||
data++;
|
||||
|
||||
/* parse each byte till we reach end of sequence byte - 0x00 */
|
||||
while (1) {
|
||||
index = *data;
|
||||
mipi_elem_exec = exec_elem[index];
|
||||
if (!mipi_elem_exec) {
|
||||
DRM_ERROR("Unsupported MIPI element, skipping sequence execution\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* goto element payload */
|
||||
data++;
|
||||
|
||||
/* execute the element specific rotines */
|
||||
data = mipi_elem_exec(intel_dsi, data);
|
||||
|
||||
/*
|
||||
* After processing the element, data should point to
|
||||
* next element or end of sequence
|
||||
* check if have we reached end of sequence
|
||||
*/
|
||||
if (*data == 0x00)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool generic_init(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
|
||||
struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
|
||||
u32 bits_per_pixel = 24;
|
||||
u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
|
||||
u32 ui_num, ui_den;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 tclk_prepare_clkzero, ths_prepare_hszero;
|
||||
u32 lp_to_hs_switch, hs_to_lp_switch;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
|
||||
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
|
||||
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
|
||||
intel_dsi->pixel_format = mipi_config->videomode_color_format << 7;
|
||||
|
||||
if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB666)
|
||||
bits_per_pixel = 18;
|
||||
else if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB565)
|
||||
bits_per_pixel = 16;
|
||||
|
||||
bitrate = (mode->clock * bits_per_pixel) / intel_dsi->lane_count;
|
||||
|
||||
intel_dsi->operation_mode = mipi_config->is_cmd_mode;
|
||||
intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
|
||||
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
|
||||
intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
|
||||
intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
|
||||
intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
|
||||
intel_dsi->init_count = mipi_config->master_init_timer;
|
||||
intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
|
||||
intel_dsi->video_frmt_cfg_bits = mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
|
||||
|
||||
switch (intel_dsi->escape_clk_div) {
|
||||
case 0:
|
||||
tlpx_ns = 50;
|
||||
break;
|
||||
case 1:
|
||||
tlpx_ns = 100;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
tlpx_ns = 200;
|
||||
break;
|
||||
default:
|
||||
tlpx_ns = 50;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (intel_dsi->lane_count) {
|
||||
case 1:
|
||||
case 2:
|
||||
extra_byte_count = 2;
|
||||
break;
|
||||
case 3:
|
||||
extra_byte_count = 4;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
extra_byte_count = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* ui(s) = 1/f [f in hz]
|
||||
* ui(ns) = 10^9 / (f*10^6) [f in Mhz] -> 10^3/f(Mhz)
|
||||
*/
|
||||
|
||||
/* in Kbps */
|
||||
ui_num = NS_KHZ_RATIO;
|
||||
ui_den = bitrate;
|
||||
|
||||
tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
|
||||
ths_prepare_hszero = mipi_config->ths_prepare_hszero;
|
||||
|
||||
/*
|
||||
* B060
|
||||
* LP byte clock = TLPX/ (8UI)
|
||||
*/
|
||||
intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
|
||||
|
||||
/* count values in UI = (ns value) * (bitrate / (2 * 10^6))
|
||||
*
|
||||
* Since txddrclkhs_i is 2xUI, all the count values programmed in
|
||||
* DPHY param register are divided by 2
|
||||
*
|
||||
* prepare count
|
||||
*/
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare, mipi_config->tclk_prepare);
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * 2);
|
||||
|
||||
/* exit zero count */
|
||||
exit_zero_cnt = DIV_ROUND_UP(
|
||||
(ths_prepare_hszero - ths_prepare_ns) * ui_den,
|
||||
ui_num * 2
|
||||
);
|
||||
|
||||
/*
|
||||
* Exit zero is unified val ths_zero and ths_exit
|
||||
* minimum value for ths_exit = 110ns
|
||||
* min (exit_zero_cnt * 2) = 110/UI
|
||||
* exit_zero_cnt = 55/UI
|
||||
*/
|
||||
if (exit_zero_cnt < (55 * ui_den / ui_num))
|
||||
if ((55 * ui_den) % ui_num)
|
||||
exit_zero_cnt += 1;
|
||||
|
||||
/* clk zero count */
|
||||
clk_zero_cnt = DIV_ROUND_UP(
|
||||
(tclk_prepare_clkzero - ths_prepare_ns)
|
||||
* ui_den, 2 * ui_num);
|
||||
|
||||
/* trail count */
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, 2 * ui_num);
|
||||
|
||||
if (prepare_cnt > PREPARE_CNT_MAX ||
|
||||
exit_zero_cnt > EXIT_ZERO_CNT_MAX ||
|
||||
clk_zero_cnt > CLK_ZERO_CNT_MAX ||
|
||||
trail_cnt > TRAIL_CNT_MAX)
|
||||
DRM_DEBUG_DRIVER("Values crossing maximum limits, restricting to max values\n");
|
||||
|
||||
if (prepare_cnt > PREPARE_CNT_MAX)
|
||||
prepare_cnt = PREPARE_CNT_MAX;
|
||||
|
||||
if (exit_zero_cnt > EXIT_ZERO_CNT_MAX)
|
||||
exit_zero_cnt = EXIT_ZERO_CNT_MAX;
|
||||
|
||||
if (clk_zero_cnt > CLK_ZERO_CNT_MAX)
|
||||
clk_zero_cnt = CLK_ZERO_CNT_MAX;
|
||||
|
||||
if (trail_cnt > TRAIL_CNT_MAX)
|
||||
trail_cnt = TRAIL_CNT_MAX;
|
||||
|
||||
/* B080 */
|
||||
intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
|
||||
clk_zero_cnt << 8 | prepare_cnt;
|
||||
|
||||
/*
|
||||
* LP to HS switch count = 4TLPX + PREP_COUNT * 2 + EXIT_ZERO_COUNT * 2
|
||||
* + 10UI + Extra Byte Count
|
||||
*
|
||||
* HS to LP switch count = THS-TRAIL + 2TLPX + Extra Byte Count
|
||||
* Extra Byte Count is calculated according to number of lanes.
|
||||
* High Low Switch Count is the Max of LP to HS and
|
||||
* HS to LP switch count
|
||||
*
|
||||
*/
|
||||
tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
|
||||
|
||||
/* B044 */
|
||||
/* FIXME:
|
||||
* The comment above does not match with the code */
|
||||
lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * 2 +
|
||||
exit_zero_cnt * 2 + 10, 8);
|
||||
|
||||
hs_to_lp_switch = DIV_ROUND_UP(mipi_config->ths_trail + 2 * tlpx_ui, 8);
|
||||
|
||||
intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
|
||||
intel_dsi->hs_to_lp_count += extra_byte_count;
|
||||
|
||||
/* B088 */
|
||||
/* LP -> HS for clock lanes
|
||||
* LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
|
||||
* extra byte count
|
||||
* 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
|
||||
* 2(in UI) + extra byte count
|
||||
* In byteclks = (4TLPX + prepare_cnt * 2 + clk_zero_cnt *2 (in UI)) /
|
||||
* 8 + extra byte count
|
||||
*/
|
||||
intel_dsi->clk_lp_to_hs_count =
|
||||
DIV_ROUND_UP(
|
||||
4 * tlpx_ui + prepare_cnt * 2 +
|
||||
clk_zero_cnt * 2,
|
||||
8);
|
||||
|
||||
intel_dsi->clk_lp_to_hs_count += extra_byte_count;
|
||||
|
||||
/* HS->LP for Clock Lanes
|
||||
* Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
|
||||
* Extra byte count
|
||||
* 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
|
||||
* In byteclks = (2*TLpx(in UI) + trail_count*2 +8)(in UI)/8 +
|
||||
* Extra byte count
|
||||
*/
|
||||
intel_dsi->clk_hs_to_lp_count =
|
||||
DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8,
|
||||
8);
|
||||
intel_dsi->clk_hs_to_lp_count += extra_byte_count;
|
||||
|
||||
DRM_DEBUG_KMS("Eot %s\n", intel_dsi->eotp_pkt ? "enabled" : "disabled");
|
||||
DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ?
|
||||
"disabled" : "enabled");
|
||||
DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
|
||||
DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
|
||||
DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
|
||||
DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);
|
||||
DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val);
|
||||
DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count);
|
||||
DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
|
||||
DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
|
||||
DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
|
||||
DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("BTA %s\n",
|
||||
intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA ?
|
||||
"disabled" : "enabled");
|
||||
|
||||
/* delays in VBT are in unit of 100us, so need to convert
|
||||
* here in ms
|
||||
* Delay (100us) * 100 /1000 = Delay / 10 (ms) */
|
||||
intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
|
||||
intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
|
||||
intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
|
||||
intel_dsi->panel_off_delay = pps->panel_off_delay / 10;
|
||||
intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int generic_mode_valid(struct intel_dsi_device *dsi,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static bool generic_mode_fixup(struct intel_dsi_device *dsi,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void generic_panel_reset(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET];
|
||||
|
||||
generic_exec_sequence(intel_dsi, sequence);
|
||||
}
|
||||
|
||||
static void generic_disable_panel_power(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET];
|
||||
|
||||
generic_exec_sequence(intel_dsi, sequence);
|
||||
}
|
||||
|
||||
static void generic_send_otp_cmds(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
|
||||
|
||||
generic_exec_sequence(intel_dsi, sequence);
|
||||
}
|
||||
|
||||
static void generic_enable(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON];
|
||||
|
||||
generic_exec_sequence(intel_dsi, sequence);
|
||||
}
|
||||
|
||||
static void generic_disable(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF];
|
||||
|
||||
generic_exec_sequence(intel_dsi, sequence);
|
||||
}
|
||||
|
||||
static enum drm_connector_status generic_detect(struct intel_dsi_device *dsi)
|
||||
{
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static bool generic_get_hw_state(struct intel_dsi_device *dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct drm_display_mode *generic_get_modes(struct intel_dsi_device *dsi)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->vbt.lfp_lvds_vbt_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
return dev_priv->vbt.lfp_lvds_vbt_mode;
|
||||
}
|
||||
|
||||
static void generic_destroy(struct intel_dsi_device *dsi) { }
|
||||
|
||||
/* Callbacks. We might not need them all. */
|
||||
struct intel_dsi_dev_ops vbt_generic_dsi_display_ops = {
|
||||
.init = generic_init,
|
||||
.mode_valid = generic_mode_valid,
|
||||
.mode_fixup = generic_mode_fixup,
|
||||
.panel_reset = generic_panel_reset,
|
||||
.disable_panel_power = generic_disable_panel_power,
|
||||
.send_otp_cmds = generic_send_otp_cmds,
|
||||
.enable = generic_enable,
|
||||
.disable = generic_disable,
|
||||
.detect = generic_detect,
|
||||
.get_hw_state = generic_get_hw_state,
|
||||
.get_modes = generic_get_modes,
|
||||
.destroy = generic_destroy,
|
||||
};
|
@ -5388,8 +5388,11 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
|
||||
I915_WRITE(GEN6_UCGCTL2,
|
||||
GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
|
||||
|
||||
/* WaDisableL3Bank2xClockGate:vlv */
|
||||
I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
|
||||
/* WaDisableL3Bank2xClockGate:vlv
|
||||
* Disabling L3 clock gating- MMIO 940c[25] = 1
|
||||
* Set bit 25, to disable L3_BANK_2x_CLK_GATING */
|
||||
I915_WRITE(GEN7_UCGCTL4,
|
||||
I915_READ(GEN7_UCGCTL4) | GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
|
||||
|
||||
I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
|
||||
|
||||
@ -5541,6 +5544,12 @@ static void gen3_init_clock_gating(struct drm_device *dev)
|
||||
|
||||
/* IIR "flip pending" means done if this bit is set */
|
||||
I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
|
||||
|
||||
/* interrupts should cause a wake up from C3 */
|
||||
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_INT_EN));
|
||||
|
||||
/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
|
||||
I915_WRITE(MI_ARB_STATE, _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
|
||||
}
|
||||
|
||||
static void i85x_init_clock_gating(struct drm_device *dev)
|
||||
@ -5548,6 +5557,10 @@ static void i85x_init_clock_gating(struct drm_device *dev)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
|
||||
|
||||
/* interrupts should cause a wake up from C3 */
|
||||
I915_WRITE(MI_STATE, _MASKED_BIT_ENABLE(MI_AGPBUSY_INT_EN) |
|
||||
_MASKED_BIT_DISABLE(MI_AGPBUSY_830_MODE));
|
||||
}
|
||||
|
||||
static void i830_init_clock_gating(struct drm_device *dev)
|
||||
@ -5599,10 +5612,25 @@ bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain)
|
||||
{
|
||||
struct i915_power_domains *power_domains;
|
||||
struct i915_power_well *power_well;
|
||||
bool is_enabled;
|
||||
int i;
|
||||
|
||||
if (dev_priv->pm.suspended)
|
||||
return false;
|
||||
|
||||
power_domains = &dev_priv->power_domains;
|
||||
is_enabled = true;
|
||||
for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
|
||||
if (power_well->always_on)
|
||||
continue;
|
||||
|
||||
return power_domains->domain_use_count[domain];
|
||||
if (!power_well->count) {
|
||||
is_enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
|
||||
@ -5745,13 +5773,34 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vlv_set_power_well(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well, bool enable)
|
||||
void __vlv_set_power_well(struct drm_i915_private *dev_priv,
|
||||
enum punit_power_well power_well_id, bool enable)
|
||||
{
|
||||
enum punit_power_well power_well_id = power_well->data;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
u32 mask;
|
||||
u32 state;
|
||||
u32 ctrl;
|
||||
enum pipe pipe;
|
||||
|
||||
if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
|
||||
if (enable) {
|
||||
/*
|
||||
* Enable the CRI clock source so we can get at the
|
||||
* display and the reference clock for VGA
|
||||
* hotplug / manual detection.
|
||||
*/
|
||||
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
|
||||
DPLL_REFA_CLK_ENABLE_VLV |
|
||||
DPLL_INTEGRATED_CRI_CLK_VLV);
|
||||
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
|
||||
} else {
|
||||
for_each_pipe(pipe)
|
||||
assert_pll_disabled(dev_priv, pipe);
|
||||
/* Assert common reset */
|
||||
I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) &
|
||||
~DPIO_CMNRST);
|
||||
}
|
||||
}
|
||||
|
||||
mask = PUNIT_PWRGT_MASK(power_well_id);
|
||||
state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
|
||||
@ -5779,6 +5828,28 @@ static void vlv_set_power_well(struct drm_i915_private *dev_priv,
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
/*
|
||||
* From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
|
||||
* 6. De-assert cmn_reset/side_reset. Same as VLV X0.
|
||||
* a. GUnit 0x2110 bit[0] set to 1 (def 0)
|
||||
* b. The other bits such as sfr settings / modesel may all
|
||||
* be set to 0.
|
||||
*
|
||||
* This should only be done on init and resume from S3 with
|
||||
* both PLLs disabled, or we risk losing DPIO and PLL
|
||||
* synchronization.
|
||||
*/
|
||||
if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC && enable)
|
||||
I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
|
||||
}
|
||||
|
||||
static void vlv_set_power_well(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well, bool enable)
|
||||
{
|
||||
enum punit_power_well power_well_id = power_well->data;
|
||||
|
||||
__vlv_set_power_well(dev_priv, power_well_id, enable);
|
||||
}
|
||||
|
||||
static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
|
||||
@ -6113,12 +6184,6 @@ static struct i915_power_well vlv_power_wells[] = {
|
||||
.data = PUNIT_POWER_WELL_DISP2D,
|
||||
.ops = &vlv_display_power_well_ops,
|
||||
},
|
||||
{
|
||||
.name = "dpio-common",
|
||||
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
|
||||
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
|
||||
.ops = &vlv_dpio_power_well_ops,
|
||||
},
|
||||
{
|
||||
.name = "dpio-tx-b-01",
|
||||
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
|
||||
@ -6155,6 +6220,12 @@ static struct i915_power_well vlv_power_wells[] = {
|
||||
.ops = &vlv_dpio_power_well_ops,
|
||||
.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
|
||||
},
|
||||
{
|
||||
.name = "dpio-common",
|
||||
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
|
||||
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
|
||||
.ops = &vlv_dpio_power_well_ops,
|
||||
},
|
||||
};
|
||||
|
||||
#define set_power_wells(power_domains, __power_wells) ({ \
|
||||
|
@ -1494,7 +1494,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
|
||||
return;
|
||||
|
||||
intel_stop_ring_buffer(ring);
|
||||
WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
|
||||
iounmap(ringbuf->virtual_start);
|
||||
|
||||
|
@ -393,26 +393,8 @@ void intel_uncore_early_sanitize(struct drm_device *dev)
|
||||
|
||||
void intel_uncore_sanitize(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg_val;
|
||||
|
||||
/* BIOS often leaves RC6 enabled, but disable it for hw init */
|
||||
intel_disable_gt_powersave(dev);
|
||||
|
||||
/* Turn off power gate, require especially for the BIOS less system */
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
|
||||
|
||||
if (reg_val & (PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_RENDER) |
|
||||
PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_MEDIA) |
|
||||
PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_DISP2D)))
|
||||
vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -967,6 +949,9 @@ static int i965_do_reset(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* FIXME: i965g/gm need a display save/restore for gpu reset. */
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Set the domains we want to reset (GRDOM/bits 2 and 3) as
|
||||
* well as the reset bit (GR/bit 0). Setting the GR bit
|
||||
|
@ -24,6 +24,17 @@
|
||||
#ifndef DRM_PLANE_HELPER_H
|
||||
#define DRM_PLANE_HELPER_H
|
||||
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
/*
|
||||
* Drivers that don't allow primary plane scaling may pass this macro in place
|
||||
* of the min/max scale parameters of the update checker function.
|
||||
*
|
||||
* Due to src being in 16.16 fixed point and dest being in integer pixels,
|
||||
* 1<<16 represents no scaling.
|
||||
*/
|
||||
#define DRM_PLANE_HELPER_NO_SCALING (1<<16)
|
||||
|
||||
/**
|
||||
* DOC: plane helpers
|
||||
*
|
||||
@ -31,6 +42,17 @@
|
||||
* planes.
|
||||
*/
|
||||
|
||||
extern int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dest,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
bool can_update_disabled,
|
||||
bool *visible);
|
||||
extern int drm_primary_helper_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
|
Loading…
Reference in New Issue
Block a user