]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'drm-intel-fixes-2014-06-06' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Fri, 6 Jun 2014 09:07:09 +0000 (19:07 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 6 Jun 2014 09:07:09 +0000 (19:07 +1000)
> 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
  ...

21 files changed:
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_uncore.c
include/drm/drm_plane_helper.h

index 239342f554b4d9dd4dab156331bf6d09be9b9671..fe94cc10cd350f8dcf06f989f7f131fb392771a9 100644 (file)
@@ -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",
index 1b15643b45869414e53ba853d476e4bc97c0ef69..6d133149cc74873fd593aff0ae1aaa9362c29c31 100644 (file)
@@ -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);
index 7b2f3bee351814dc8065def8284206f7267abf3c..cad1683d8bb527cc3c5e3fe9b163d581ff42ec53 100644 (file)
@@ -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 \
index 169fc2d8c554e85f86adf2cf4f5e0b4b32edc432..601caa88c0928cb818c6af27cbb9f25c0a4bebf2 100644 (file)
@@ -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");
index 5b5b82c3f57086962bf61d47958bcb0fefb786dd..651e65e051c08a8e25189719aa38f6226f699271 100644 (file)
@@ -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
        }
index 8e78703e45cf5148be6cfeeb9839adc450a1699c..49414d30e8d42d3068cbd21990f1403e3e8b1f5a 100644 (file)
@@ -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;
index bbcd35abf2471cbd14736b654802c4b44c0bc0f1..f36126383d260166a950ad20c72b69637246c550 100644 (file)
@@ -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));
        }
index 931b906f292a95e12d0884cc85d0650f8904d962..eec820aec0224a975325a439c350e57036bd5dc9 100644 (file)
@@ -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;
 }
 
index cbf31cbfa0840f430e23f98870e1ff90ce66b341..cf288a95347c02c81d195e86f9e8bd8469660314 100644 (file)
@@ -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;
index 5122254e7213a9879c41be035189f144b8556edc..e691b30b28179ab9d026daeaa4c6a5e176062327 100644 (file)
@@ -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)
index 6b6509656f16f6e18c2d8623a21887d26865621b..1ee98f121a00fbe4be26cf60187d9b7a81983caf 100644 (file)
@@ -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,
index 6009debebaaf648c8f1c10ecb13de33bf2427058..b98667796337d776b1d1d39c677a5dfffe6b32b6 100644 (file)
@@ -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
index 7a4c7c98378a91901c7bea3c7cbd966a26bebd2e..efd3cf50cb0f6a647d670a0f2a7b886b4e1d0b8a 100644 (file)
@@ -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;
-
-       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;
+       uint32_t cntl;
 
-                       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;
                }
+               cntl |= pipe << 28; /* Connect to correct pipe */
+       }
+       if (intel_crtc->cursor_cntl != cntl) {
                I915_WRITE(CURCNTR(pipe), cntl);
-
-               intel_crtc->cursor_visible = visible;
+               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;
-
-       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) {
+       uint32_t cntl;
+
+       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);
+       }
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               cntl |= CURSOR_PIPE_CSC_ENABLE;
 
-               intel_crtc->cursor_visible = visible;
+       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 },
 
index 0de04983501e12969fcc127293a053a8c10452f4..bda0ae3d80cc667a5f2706fade10ed58825d34ff 100644 (file)
@@ -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);
index 2525cdd5234386a36dd1227fdfa42f787103bd39..02f99d768d49f4f76d6eb1ec9de683911d3332c5 100644 (file)
 
 /* 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;
index e3f4e91c526f6693940c0cd1322e794b2dc43693..31db33d3e5cc5d0616d36d69a6230ba7fe496d40 100644 (file)
@@ -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 */
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
new file mode 100644 (file)
index 0000000..21a0d34
--- /dev/null
@@ -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,
+};
index 906d06f73e51f5d96d82c03a234c949876c34fae..d1e53abec1b5f808fbf5457f565f2343689e41f6 100644 (file)
@@ -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) ({               \
index 3379722d0e6d11f73b0d50db7afcff6669351423..279488addf3f6bd7afb194bf29479a9228390460 100644 (file)
@@ -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);
 
index 2f5d5d3f004346fa2ab9dcc18316e09875cb501e..79cba593df0d33dd1bb1fe6732e94d62ec39fe73 100644 (file)
@@ -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
index c5e7ab9503c822805469f396d348d175dea343b2..52e6870534b24ad90bec35526d23a4dda690765d 100644 (file)
 #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
  *
  * 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,