Browse Source

Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux

Pull drm updates from Dave Airlie:
 "Okay this is the big one, I was stalled on the fbdev pull req as I
  stupidly let fbdev guys merge a patch I required to fix a warning with
  some patches I had, they ended up merging the patch from the wrong
  place, but the warning should be fixed.  In future I'll just take the
  patch myself!

  Outside drm:

  There are some snd changes for the HDMI audio interactions on haswell,
  they've been acked for inclusion via my tree.  This relies on the
  wound/wait tree from Ingo which is already merged.

  Major changes:

  AMD finally released the dynamic power management code for all their
  GPUs from r600->present day, this is great, off by default for now but
  also a huge amount of code, in fact it is most of this pull request.

  Since it landed there has been a lot of community testing and Alex has
  sent a lot of fixes for any bugs found so far.  I suspect radeon might
  now be the biggest kernel driver ever :-P p.s.  radeon.dpm=1 to enable
  dynamic powermanagement for anyone.

  New drivers:

  Renesas r-car display unit.

  Other highlights:

   - core: GEM CMA prime support, use new w/w mutexs for TTM
     reservations, cursor hotspot, doc updates
   - dvo chips: chrontel 7010B support
   - i915: Haswell (fbc, ips, vecs, watermarks, audio powerwell),
     Valleyview (enabled by default, rc6), lots of pll reworking, 30bpp
     support (this time for sure)
   - nouveau: async buffer object deletion, context/register init
     updates, kernel vp2 engine support, GF117 support, GK110 accel
     support (with external nvidia ucode), context cleanups.
   - exynos: memory leak fixes, Add S3C64XX SoC series support, device
     tree updates, common clock framework support,
   - qxl: cursor hotspot support, multi-monitor support, suspend/resume
     support
   - mgag200: hw cursor support, g200 mode limiting
   - shmobile: prime support
   - tegra: fixes mostly

  I've been banging on this quite a lot due to the size of it, and it
  seems to okay on everything I've tested it on."

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (811 commits)
  drm/radeon/dpm: implement vblank_too_short callback for si
  drm/radeon/dpm: implement vblank_too_short callback for cayman
  drm/radeon/dpm: implement vblank_too_short callback for btc
  drm/radeon/dpm: implement vblank_too_short callback for evergreen
  drm/radeon/dpm: implement vblank_too_short callback for 7xx
  drm/radeon/dpm: add checks against vblank time
  drm/radeon/dpm: add helper to calculate vblank time
  drm/radeon: remove stray line in old pm code
  drm/radeon/dpm: fix display_gap programming on rv7xx
  drm/nvc0/gr: fix gpc firmware regression
  drm/nouveau: fix minor thinko causing bo moves to not be async on kepler
  drm/radeon/dpm: implement force performance level for TN
  drm/radeon/dpm: implement force performance level for ON/LN
  drm/radeon/dpm: implement force performance level for SI
  drm/radeon/dpm: implement force performance level for cayman
  drm/radeon/dpm: implement force performance levels for 7xx/eg/btc
  drm/radeon/dpm: add infrastructure to force performance levels
  drm/radeon: fix surface setup on r1xx
  drm/radeon: add support for 3d perf states on older asics
  drm/radeon: set default clocks for SI when DPM is disabled
  ...
Linus Torvalds 12 years ago
parent
commit
2e17c5a97e
100 changed files with 5739 additions and 3479 deletions
  1. 2 0
      Documentation/DocBook/device-drivers.tmpl
  2. 219 52
      Documentation/DocBook/drm.tmpl
  3. 8 0
      Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt
  4. 1 0
      Documentation/devicetree/bindings/video/display-timing.txt
  5. 7 6
      Documentation/devicetree/bindings/video/exynos_hdmi.txt
  6. 5 2
      Documentation/devicetree/bindings/video/exynos_hdmiddc.txt
  7. 5 2
      Documentation/devicetree/bindings/video/exynos_hdmiphy.txt
  8. 7 2
      Documentation/devicetree/bindings/video/exynos_mixer.txt
  9. 5 11
      Documentation/fb/uvesafb.txt
  10. 5 3
      MAINTAINERS
  11. 2 2
      arch/arm/boot/dts/cros5250-common.dtsi
  12. 2 2
      arch/arm/boot/dts/exynos5250-smdk5250.dts
  13. 2 2
      arch/arm/boot/dts/exynos5250.dtsi
  14. 7 0
      arch/x86/include/asm/io.h
  15. 9 1
      arch/x86/include/asm/mtrr.h
  16. 71 0
      arch/x86/kernel/cpu/mtrr/main.c
  17. 1 1
      drivers/base/Makefile
  18. 39 0
      drivers/base/reservation.c
  19. 2 2
      drivers/char/agp/ati-agp.c
  20. 5 3
      drivers/char/agp/frontend.c
  21. 3 3
      drivers/char/agp/nvidia-agp.c
  22. 3 0
      drivers/gpu/drm/Kconfig
  23. 3 1
      drivers/gpu/drm/Makefile
  24. 18 2
      drivers/gpu/drm/ast/ast_drv.h
  25. 3 2
      drivers/gpu/drm/ast/ast_fb.c
  26. 3 28
      drivers/gpu/drm/ast/ast_ttm.c
  27. 19 2
      drivers/gpu/drm/cirrus/cirrus_drv.h
  28. 3 2
      drivers/gpu/drm/cirrus/cirrus_fbdev.c
  29. 4 29
      drivers/gpu/drm/cirrus/cirrus_ttm.c
  30. 18 8
      drivers/gpu/drm/drm_bufs.c
  31. 147 44
      drivers/gpu/drm/drm_crtc.c
  32. 25 20
      drivers/gpu/drm/drm_crtc_helper.c
  33. 1 0
      drivers/gpu/drm/drm_drv.c
  34. 96 19
      drivers/gpu/drm/drm_edid.c
  35. 1 2
      drivers/gpu/drm/drm_edid_load.c
  36. 39 4
      drivers/gpu/drm/drm_fb_helper.c
  37. 20 5
      drivers/gpu/drm/drm_fops.c
  38. 65 48
      drivers/gpu/drm/drm_gem.c
  39. 165 40
      drivers/gpu/drm/drm_gem_cma_helper.c
  40. 14 1
      drivers/gpu/drm/drm_ioctl.c
  41. 22 23
      drivers/gpu/drm/drm_mm.c
  42. 11 3
      drivers/gpu/drm/drm_modes.c
  43. 4 4
      drivers/gpu/drm/drm_pci.c
  44. 146 42
      drivers/gpu/drm/drm_prime.c
  45. 295 0
      drivers/gpu/drm/drm_rect.c
  46. 4 10
      drivers/gpu/drm/drm_stub.c
  47. 29 4
      drivers/gpu/drm/drm_sysfs.c
  48. 3 3
      drivers/gpu/drm/drm_trace.h
  49. 10 14
      drivers/gpu/drm/drm_vm.c
  50. 2 0
      drivers/gpu/drm/exynos/exynos_ddc.c
  51. 6 14
      drivers/gpu/drm/exynos/exynos_drm_buf.c
  52. 2 49
      drivers/gpu/drm/exynos/exynos_drm_connector.c
  53. 0 12
      drivers/gpu/drm/exynos/exynos_drm_core.c
  54. 5 34
      drivers/gpu/drm/exynos/exynos_drm_crtc.c
  55. 0 6
      drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
  56. 8 21
      drivers/gpu/drm/exynos/exynos_drm_drv.c
  57. 2 2
      drivers/gpu/drm/exynos/exynos_drm_drv.h
  58. 1 27
      drivers/gpu/drm/exynos/exynos_drm_encoder.c
  59. 0 10
      drivers/gpu/drm/exynos/exynos_drm_fb.c
  60. 0 8
      drivers/gpu/drm/exynos/exynos_drm_fbdev.c
  61. 53 76
      drivers/gpu/drm/exynos/exynos_drm_fimc.c
  62. 74 72
      drivers/gpu/drm/exynos/exynos_drm_fimd.c
  63. 7 11
      drivers/gpu/drm/exynos/exynos_drm_g2d.c
  64. 8 30
      drivers/gpu/drm/exynos/exynos_drm_gem.c
  65. 41 61
      drivers/gpu/drm/exynos/exynos_drm_gsc.c
  66. 11 52
      drivers/gpu/drm/exynos/exynos_drm_hdmi.c
  67. 3 3
      drivers/gpu/drm/exynos/exynos_drm_hdmi.h
  68. 67 135
      drivers/gpu/drm/exynos/exynos_drm_ipp.c
  69. 0 16
      drivers/gpu/drm/exynos/exynos_drm_plane.c
  70. 18 35
      drivers/gpu/drm/exynos/exynos_drm_rotator.c
  71. 6 47
      drivers/gpu/drm/exynos/exynos_drm_vidi.c
  72. 56 75
      drivers/gpu/drm/exynos/exynos_hdmi.c
  73. 4 0
      drivers/gpu/drm/exynos/exynos_hdmiphy.c
  74. 65 59
      drivers/gpu/drm/exynos/exynos_mixer.c
  75. 7 0
      drivers/gpu/drm/exynos/regs-mixer.h
  76. 1 0
      drivers/gpu/drm/i915/Makefile
  77. 26 2
      drivers/gpu/drm/i915/dvo_ch7xxx.c
  78. 376 97
      drivers/gpu/drm/i915/i915_debugfs.c
  79. 37 53
      drivers/gpu/drm/i915/i915_dma.c
  80. 61 55
      drivers/gpu/drm/i915/i915_drv.c
  81. 249 110
      drivers/gpu/drm/i915/i915_drv.h
  82. 224 69
      drivers/gpu/drm/i915/i915_gem.c
  83. 88 30
      drivers/gpu/drm/i915/i915_gem_context.c
  84. 14 4
      drivers/gpu/drm/i915/i915_gem_execbuffer.c
  85. 83 31
      drivers/gpu/drm/i915/i915_gem_gtt.c
  86. 23 8
      drivers/gpu/drm/i915/i915_gem_stolen.c
  87. 662 194
      drivers/gpu/drm/i915/i915_irq.c
  88. 432 245
      drivers/gpu/drm/i915/i915_reg.h
  89. 10 0
      drivers/gpu/drm/i915/i915_suspend.c
  90. 55 19
      drivers/gpu/drm/i915/i915_sysfs.c
  91. 45 45
      drivers/gpu/drm/i915/i915_ums.c
  92. 50 50
      drivers/gpu/drm/i915/intel_bios.c
  93. 32 3
      drivers/gpu/drm/i915/intel_crt.c
  94. 285 469
      drivers/gpu/drm/i915/intel_ddi.c
  95. 183 403
      drivers/gpu/drm/i915/intel_display.c
  96. 445 214
      drivers/gpu/drm/i915/intel_dp.c
  97. 141 45
      drivers/gpu/drm/i915/intel_drv.h
  98. 31 0
      drivers/gpu/drm/i915/intel_dvo.c
  99. 11 17
      drivers/gpu/drm/i915/intel_fb.c
  100. 151 7
      drivers/gpu/drm/i915/intel_hdmi.c

+ 2 - 0
Documentation/DocBook/device-drivers.tmpl

@@ -126,6 +126,8 @@ X!Edrivers/base/interface.c
      </sect1>
      <sect1><title>Device Drivers DMA Management</title>
 !Edrivers/base/dma-buf.c
+!Edrivers/base/reservation.c
+!Iinclude/linux/reservation.h
 !Edrivers/base/dma-coherent.c
 !Edrivers/base/dma-mapping.c
      </sect1>

+ 219 - 52
Documentation/DocBook/drm.tmpl

@@ -186,11 +186,12 @@
           <varlistentry>
             <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
             <listitem><para>
-              DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler. The
-              DRM core will automatically register an interrupt handler when the
-              flag is set. DRIVER_IRQ_SHARED indicates whether the device &amp;
-              handler support shared IRQs (note that this is required of PCI
-              drivers).
+              DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler
+              managed by the DRM Core. The core will support simple IRQ handler
+              installation when the flag is set. The installation process is
+              described in <xref linkend="drm-irq-registration"/>.</para>
+              <para>DRIVER_IRQ_SHARED indicates whether the device &amp; handler
+              support shared IRQs (note that this is required of PCI  drivers).
             </para></listitem>
           </varlistentry>
           <varlistentry>
@@ -344,50 +345,71 @@ char *date;</synopsis>
           The DRM core tries to facilitate IRQ handler registration and
           unregistration by providing <function>drm_irq_install</function> and
           <function>drm_irq_uninstall</function> functions. Those functions only
-          support a single interrupt per device.
-        </para>
-  <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
-        <para>
-          Both functions get the device IRQ by calling
-          <function>drm_dev_to_irq</function>. This inline function will call a
-          bus-specific operation to retrieve the IRQ number. For platform devices,
-          <function>platform_get_irq</function>(..., 0) is used to retrieve the
-          IRQ number.
-        </para>
-        <para>
-          <function>drm_irq_install</function> starts by calling the
-          <methodname>irq_preinstall</methodname> driver operation. The operation
-          is optional and must make sure that the interrupt will not get fired by
-          clearing all pending interrupt flags or disabling the interrupt.
-        </para>
-        <para>
-          The IRQ will then be requested by a call to
-          <function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
-          feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
-          requested.
-        </para>
-        <para>
-          The IRQ handler function must be provided as the mandatory irq_handler
-          driver operation. It will get passed directly to
-          <function>request_irq</function> and thus has the same prototype as all
-          IRQ handlers. It will get called with a pointer to the DRM device as the
-          second argument.
-        </para>
-        <para>
-          Finally the function calls the optional
-          <methodname>irq_postinstall</methodname> driver operation. The operation
-          usually enables interrupts (excluding the vblank interrupt, which is
-          enabled separately), but drivers may choose to enable/disable interrupts
-          at a different time.
-        </para>
-        <para>
-          <function>drm_irq_uninstall</function> is similarly used to uninstall an
-          IRQ handler. It starts by waking up all processes waiting on a vblank
-          interrupt to make sure they don't hang, and then calls the optional
-          <methodname>irq_uninstall</methodname> driver operation. The operation
-          must disable all hardware interrupts. Finally the function frees the IRQ
-          by calling <function>free_irq</function>.
+          support a single interrupt per device, devices that use more than one
+          IRQs need to be handled manually.
         </para>
+        <sect4>
+          <title>Managed IRQ Registration</title>
+          <para>
+            Both the <function>drm_irq_install</function> and
+	    <function>drm_irq_uninstall</function> functions get the device IRQ by
+	    calling <function>drm_dev_to_irq</function>. This inline function will
+	    call a bus-specific operation to retrieve the IRQ number. For platform
+	    devices, <function>platform_get_irq</function>(..., 0) is used to
+	    retrieve the IRQ number.
+          </para>
+          <para>
+            <function>drm_irq_install</function> starts by calling the
+            <methodname>irq_preinstall</methodname> driver operation. The operation
+            is optional and must make sure that the interrupt will not get fired by
+            clearing all pending interrupt flags or disabling the interrupt.
+          </para>
+          <para>
+            The IRQ will then be requested by a call to
+            <function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
+            feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
+            requested.
+          </para>
+          <para>
+            The IRQ handler function must be provided as the mandatory irq_handler
+            driver operation. It will get passed directly to
+            <function>request_irq</function> and thus has the same prototype as all
+            IRQ handlers. It will get called with a pointer to the DRM device as the
+            second argument.
+          </para>
+          <para>
+            Finally the function calls the optional
+            <methodname>irq_postinstall</methodname> driver operation. The operation
+            usually enables interrupts (excluding the vblank interrupt, which is
+            enabled separately), but drivers may choose to enable/disable interrupts
+            at a different time.
+          </para>
+          <para>
+            <function>drm_irq_uninstall</function> is similarly used to uninstall an
+            IRQ handler. It starts by waking up all processes waiting on a vblank
+            interrupt to make sure they don't hang, and then calls the optional
+            <methodname>irq_uninstall</methodname> driver operation. The operation
+            must disable all hardware interrupts. Finally the function frees the IRQ
+            by calling <function>free_irq</function>.
+          </para>
+        </sect4>
+        <sect4>
+          <title>Manual IRQ Registration</title>
+          <para>
+            Drivers that require multiple interrupt handlers can't use the managed
+            IRQ registration functions. In that case IRQs must be registered and
+            unregistered manually (usually with the <function>request_irq</function>
+            and <function>free_irq</function> functions, or their devm_* equivalent).
+          </para>
+          <para>
+            When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ
+            driver feature flag, and must not provide the
+	    <methodname>irq_handler</methodname> driver operation. They must set the
+	    <structname>drm_device</structname> <structfield>irq_enabled</structfield>
+	    field to 1 upon registration of the IRQs, and clear it to 0 after
+	    unregistering the IRQs.
+          </para>
+        </sect4>
       </sect3>
       <sect3>
         <title>Memory Manager Initialization</title>
@@ -1213,6 +1235,15 @@ int max_width, max_height;</synopsis>
         <sect4>
           <title>Miscellaneous</title>
           <itemizedlist>
+            <listitem>
+              <synopsis>void (*set_property)(struct drm_crtc *crtc,
+                     struct drm_property *property, uint64_t value);</synopsis>
+              <para>
+                Set the value of the given CRTC property to
+                <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
+                for more information about properties.
+              </para>
+            </listitem>
             <listitem>
               <synopsis>void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
                         uint32_t start, uint32_t size);</synopsis>
@@ -1363,6 +1394,15 @@ int max_width, max_height;</synopsis>
               <xref linkend="drm-kms-init"/>.
             </para>
           </listitem>
+          <listitem>
+            <synopsis>void (*set_property)(struct drm_plane *plane,
+                     struct drm_property *property, uint64_t value);</synopsis>
+            <para>
+              Set the value of the given plane property to
+              <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
+              for more information about properties.
+            </para>
+          </listitem>
         </itemizedlist>
       </sect3>
     </sect2>
@@ -1571,6 +1611,15 @@ int max_width, max_height;</synopsis>
         <sect4>
           <title>Miscellaneous</title>
           <itemizedlist>
+            <listitem>
+              <synopsis>void (*set_property)(struct drm_connector *connector,
+                     struct drm_property *property, uint64_t value);</synopsis>
+              <para>
+                Set the value of the given connector property to
+                <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
+                for more information about properties.
+              </para>
+            </listitem>
             <listitem>
               <synopsis>void (*destroy)(struct drm_connector *connector);</synopsis>
               <para>
@@ -1846,10 +1895,6 @@ void intel_crt_init(struct drm_device *dev)
           <synopsis>bool (*mode_fixup)(struct drm_encoder *encoder,
                        const struct drm_display_mode *mode,
                        struct drm_display_mode *adjusted_mode);</synopsis>
-          <note><para>
-            FIXME: The mode argument be const, but the i915 driver modifies
-            mode-&gt;clock in <function>intel_dp_mode_fixup</function>.
-          </para></note>
           <para>
             Let encoders adjust the requested mode or reject it completely. This
             operation returns true if the mode is accepted (possibly after being
@@ -2161,6 +2206,128 @@ void intel_crt_init(struct drm_device *dev)
       <title>EDID Helper Functions Reference</title>
 !Edrivers/gpu/drm/drm_edid.c
     </sect2>
+    <sect2>
+      <title>Rectangle Utilities Reference</title>
+!Pinclude/drm/drm_rect.h rect utils
+!Iinclude/drm/drm_rect.h
+!Edrivers/gpu/drm/drm_rect.c
+    </sect2>
+  </sect1>
+
+  <!-- Internals: kms properties -->
+
+  <sect1 id="drm-kms-properties">
+    <title>KMS Properties</title>
+    <para>
+      Drivers may need to expose additional parameters to applications than
+      those described in the previous sections. KMS supports attaching
+      properties to CRTCs, connectors and planes and offers a userspace API to
+      list, get and set the property values.
+    </para>
+    <para>
+      Properties are identified by a name that uniquely defines the property
+      purpose, and store an associated value. For all property types except blob
+      properties the value is a 64-bit unsigned integer.
+    </para>
+    <para>
+      KMS differentiates between properties and property instances. Drivers
+      first create properties and then create and associate individual instances
+      of those properties to objects. A property can be instantiated multiple
+      times and associated with different objects. Values are stored in property
+      instances, and all other property information are stored in the propery
+      and shared between all instances of the property.
+    </para>
+    <para>
+      Every property is created with a type that influences how the KMS core
+      handles the property. Supported property types are
+      <variablelist>
+        <varlistentry>
+          <term>DRM_MODE_PROP_RANGE</term>
+          <listitem><para>Range properties report their minimum and maximum
+            admissible values. The KMS core verifies that values set by
+            application fit in that range.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_MODE_PROP_ENUM</term>
+          <listitem><para>Enumerated properties take a numerical value that
+            ranges from 0 to the number of enumerated values defined by the
+            property minus one, and associate a free-formed string name to each
+            value. Applications can retrieve the list of defined value-name pairs
+            and use the numerical value to get and set property instance values.
+            </para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_MODE_PROP_BITMASK</term>
+          <listitem><para>Bitmask properties are enumeration properties that
+            additionally restrict all enumerated values to the 0..63 range.
+            Bitmask property instance values combine one or more of the
+            enumerated bits defined by the property.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_MODE_PROP_BLOB</term>
+          <listitem><para>Blob properties store a binary blob without any format
+            restriction. The binary blobs are created as KMS standalone objects,
+            and blob property instance values store the ID of their associated
+            blob object.</para>
+	    <para>Blob properties are only used for the connector EDID property
+	    and cannot be created by drivers.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </para>
+    <para>
+      To create a property drivers call one of the following functions depending
+      on the property type. All property creation functions take property flags
+      and name, as well as type-specific arguments.
+      <itemizedlist>
+        <listitem>
+          <synopsis>struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
+                                               const char *name,
+                                               uint64_t min, uint64_t max);</synopsis>
+          <para>Create a range property with the given minimum and maximum
+            values.</para>
+        </listitem>
+        <listitem>
+          <synopsis>struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
+                                              const char *name,
+                                              const struct drm_prop_enum_list *props,
+                                              int num_values);</synopsis>
+          <para>Create an enumerated property. The <parameter>props</parameter>
+            argument points to an array of <parameter>num_values</parameter>
+            value-name pairs.</para>
+        </listitem>
+        <listitem>
+          <synopsis>struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
+                                                 int flags, const char *name,
+                                                 const struct drm_prop_enum_list *props,
+                                                 int num_values);</synopsis>
+          <para>Create a bitmask property. The <parameter>props</parameter>
+            argument points to an array of <parameter>num_values</parameter>
+            value-name pairs.</para>
+        </listitem>
+      </itemizedlist>
+    </para>
+    <para>
+      Properties can additionally be created as immutable, in which case they
+      will be read-only for applications but can be modified by the driver. To
+      create an immutable property drivers must set the DRM_MODE_PROP_IMMUTABLE
+      flag at property creation time.
+    </para>
+    <para>
+      When no array of value-name pairs is readily available at property
+      creation time for enumerated or range properties, drivers can create
+      the property using the <function>drm_property_create</function> function
+      and manually add enumeration value-name pairs by calling the
+      <function>drm_property_add_enum</function> function. Care must be taken to
+      properly specify the property type through the <parameter>flags</parameter>
+      argument.
+    </para>
+    <para>
+      After creating properties drivers can attach property instances to CRTC,
+      connector and plane objects by calling the
+      <function>drm_object_attach_property</function>. The function takes a
+      pointer to the target object, a pointer to the previously created property
+      and an initial instance value.
+    </para>
   </sect1>
 
   <!-- Internals: vertical blanking -->

+ 8 - 0
Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt

@@ -10,6 +10,14 @@ Recommended properties:
    services interrupts for this device.
  - ti,hwmods: Name of the hwmod associated to the LCDC
 
+Optional properties:
+ - max-bandwidth: The maximum pixels per second that the memory
+   interface / lcd controller combination can sustain
+ - max-width: The maximum horizontal pixel width supported by
+   the lcd controller.
+ - max-pixelclock: The maximum pixel clock that can be supported
+   by the lcd controller in KHz.
+
 Example:
 
 	fb: fb@4830e000 {

+ 1 - 0
Documentation/devicetree/bindings/video/display-timing.txt

@@ -34,6 +34,7 @@ optional properties:
 			- ignored     = ignored
  - interlaced (bool): boolean to enable interlaced mode
  - doublescan (bool): boolean to enable doublescan mode
+ - doubleclk (bool): boolean to enable doubleclock mode
 
 All the optional properties that are not bool follow the following logic:
     <1>: high active

+ 7 - 6
Documentation/devicetree/bindings/video/exynos_hdmi.txt

@@ -1,22 +1,23 @@
 Device-Tree bindings for drm hdmi driver
 
 Required properties:
-- compatible: value should be "samsung,exynos5-hdmi".
+- compatible: value should be one among the following:
+	1) "samsung,exynos5-hdmi" <DEPRECATED>
+	2) "samsung,exynos4210-hdmi"
+	3) "samsung,exynos4212-hdmi"
 - reg: physical base address of the hdmi and length of memory mapped
 	region.
 - interrupts: interrupt number to the cpu.
 - hpd-gpio: following information about the hotplug gpio pin.
 	a) phandle of the gpio controller node.
 	b) pin number within the gpio controller.
-	c) pin function mode.
-	d) optional flags and pull up/down.
-	e) drive strength.
+	c) optional flags and pull up/down.
 
 Example:
 
 	hdmi {
-		compatible = "samsung,exynos5-hdmi";
+		compatible = "samsung,exynos4212-hdmi";
 		reg = <0x14530000 0x100000>;
 		interrupts = <0 95 0>;
-		hpd-gpio = <&gpx3 7 0xf 1 3>;
+		hpd-gpio = <&gpx3 7 1>;
 	};

+ 5 - 2
Documentation/devicetree/bindings/video/exynos_hdmiddc.txt

@@ -1,12 +1,15 @@
 Device-Tree bindings for hdmiddc driver
 
 Required properties:
-- compatible: value should be "samsung,exynos5-hdmiddc".
+- compatible: value should be one of the following
+	1) "samsung,exynos5-hdmiddc" <DEPRECATED>
+	2) "samsung,exynos4210-hdmiddc"
+
 - reg: I2C address of the hdmiddc device.
 
 Example:
 
 	hdmiddc {
-		compatible = "samsung,exynos5-hdmiddc";
+		compatible = "samsung,exynos4210-hdmiddc";
 		reg = <0x50>;
 	};

+ 5 - 2
Documentation/devicetree/bindings/video/exynos_hdmiphy.txt

@@ -1,12 +1,15 @@
 Device-Tree bindings for hdmiphy driver
 
 Required properties:
-- compatible: value should be "samsung,exynos5-hdmiphy".
+- compatible: value should be one of the following:
+	1) "samsung,exynos5-hdmiphy" <DEPRECATED>
+	2) "samsung,exynos4210-hdmiphy".
+	3) "samsung,exynos4212-hdmiphy".
 - reg: I2C address of the hdmiphy device.
 
 Example:
 
 	hdmiphy {
-		compatible = "samsung,exynos5-hdmiphy";
+		compatible = "samsung,exynos4210-hdmiphy";
 		reg = <0x38>;
 	};

+ 7 - 2
Documentation/devicetree/bindings/video/exynos_mixer.txt

@@ -1,7 +1,12 @@
 Device-Tree bindings for mixer driver
 
 Required properties:
-- compatible: value should be "samsung,exynos5-mixer".
+- compatible: value should be one of the following:
+	1) "samsung,exynos5-mixer" <DEPRECATED>
+	2) "samsung,exynos4210-mixer"
+	3) "samsung,exynos5250-mixer"
+	4) "samsung,exynos5420-mixer"
+
 - reg: physical base address of the mixer and length of memory mapped
 	region.
 - interrupts: interrupt number to the cpu.
@@ -9,7 +14,7 @@ Required properties:
 Example:
 
 	mixer {
-		compatible = "samsung,exynos5-mixer";
+		compatible = "samsung,exynos5250-mixer";
 		reg = <0x14450000 0x10000>;
 		interrupts = <0 94 0>;
 	};

+ 5 - 11
Documentation/fb/uvesafb.txt

@@ -81,17 +81,11 @@ pmipal  Use the protected mode interface for palette changes.
 
 mtrr:n  Setup memory type range registers for the framebuffer
         where n:
-              0 - disabled (equivalent to nomtrr) (default)
-              1 - uncachable
-              2 - write-back
-              3 - write-combining
-              4 - write-through
-
-        If you see the following in dmesg, choose the type that matches
-        the old one.  In this example, use "mtrr:2".
-...
-mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
-...
+              0 - disabled (equivalent to nomtrr)
+              3 - write-combining (default)
+
+	Values other than 0 and 3 will result in a warning and will be
+	treated just like 3.
 
 nomtrr  Do not use memory type range registers.
 

+ 5 - 3
MAINTAINERS

@@ -2730,12 +2730,14 @@ F:	include/drm/exynos*
 F:	include/uapi/drm/exynos*
 
 DRM DRIVERS FOR NVIDIA TEGRA
-M:	Thierry Reding <thierry.reding@avionic-design.de>
+M:	Thierry Reding <thierry.reding@gmail.com>
+M:	Terje Bergström <tbergstrom@nvidia.com>
 L:	dri-devel@lists.freedesktop.org
 L:	linux-tegra@vger.kernel.org
-T:	git git://gitorious.org/thierryreding/linux.git
+T:	git git://anongit.freedesktop.org/tegra/linux.git
 S:	Maintained
-F:	drivers/gpu/drm/tegra/
+F:	drivers/gpu/host1x/
+F:	include/uapi/drm/tegra_drm.h
 F:	Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
 
 DSBR100 USB FM RADIO DRIVER

+ 2 - 2
arch/arm/boot/dts/cros5250-common.dtsi

@@ -190,7 +190,7 @@
 		samsung,i2c-max-bus-freq = <66000>;
 
 		hdmiddc@50 {
-			compatible = "samsung,exynos5-hdmiddc";
+			compatible = "samsung,exynos4210-hdmiddc";
 			reg = <0x50>;
 		};
 	};
@@ -224,7 +224,7 @@
 		samsung,i2c-max-bus-freq = <378000>;
 
 		hdmiphy@38 {
-			compatible = "samsung,exynos5-hdmiphy";
+			compatible = "samsung,exynos4212-hdmiphy";
 			reg = <0x38>;
 		};
 	};

+ 2 - 2
arch/arm/boot/dts/exynos5250-smdk5250.dts

@@ -105,7 +105,7 @@
 		samsung,i2c-max-bus-freq = <66000>;
 
 		hdmiddc@50 {
-			compatible = "samsung,exynos5-hdmiddc";
+			compatible = "samsung,exynos4210-hdmiddc";
 			reg = <0x50>;
 		};
 	};
@@ -135,7 +135,7 @@
 		samsung,i2c-max-bus-freq = <66000>;
 
 		hdmiphy@38 {
-			compatible = "samsung,exynos5-hdmiphy";
+			compatible = "samsung,exynos4212-hdmiphy";
 			reg = <0x38>;
 		};
 	};

+ 2 - 2
arch/arm/boot/dts/exynos5250.dtsi

@@ -599,7 +599,7 @@
 	};
 
 	hdmi {
-		compatible = "samsung,exynos5-hdmi";
+		compatible = "samsung,exynos4212-hdmi";
 		reg = <0x14530000 0x70000>;
 		interrupts = <0 95 0>;
 		clocks = <&clock 333>, <&clock 136>, <&clock 137>,
@@ -609,7 +609,7 @@
 	};
 
 	mixer {
-		compatible = "samsung,exynos5-mixer";
+		compatible = "samsung,exynos5250-mixer";
 		reg = <0x14450000 0x10000>;
 		interrupts = <0 94 0>;
 	};

+ 7 - 0
arch/x86/include/asm/io.h

@@ -345,4 +345,11 @@ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
 
 #define IO_SPACE_LIMIT 0xffff
 
+#ifdef CONFIG_MTRR
+extern int __must_check arch_phys_wc_add(unsigned long base,
+					 unsigned long size);
+extern void arch_phys_wc_del(int handle);
+#define arch_phys_wc_add arch_phys_wc_add
+#endif
+
 #endif /* _ASM_X86_IO_H */

+ 9 - 1
arch/x86/include/asm/mtrr.h

@@ -26,7 +26,10 @@
 #include <uapi/asm/mtrr.h>
 
 
-/*  The following functions are for use by other drivers  */
+/*
+ * The following functions are for use by other drivers that cannot use
+ * arch_phys_wc_add and arch_phys_wc_del.
+ */
 # ifdef CONFIG_MTRR
 extern u8 mtrr_type_lookup(u64 addr, u64 end);
 extern void mtrr_save_fixed_ranges(void *);
@@ -45,6 +48,7 @@ extern void mtrr_aps_init(void);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
+extern int phys_wc_to_mtrr_index(int handle);
 #  else
 static inline u8 mtrr_type_lookup(u64 addr, u64 end)
 {
@@ -80,6 +84,10 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
+static inline int phys_wc_to_mtrr_index(int handle)
+{
+	return -1;
+}
 
 #define mtrr_ap_init() do {} while (0)
 #define mtrr_bp_init() do {} while (0)

+ 71 - 0
arch/x86/kernel/cpu/mtrr/main.c

@@ -51,9 +51,13 @@
 #include <asm/e820.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
+#include <asm/pat.h>
 
 #include "mtrr.h"
 
+/* arch_phys_wc_add returns an MTRR register index plus this offset. */
+#define MTRR_TO_PHYS_WC_OFFSET 1000
+
 u32 num_var_ranges;
 
 unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
@@ -525,6 +529,73 @@ int mtrr_del(int reg, unsigned long base, unsigned long size)
 }
 EXPORT_SYMBOL(mtrr_del);
 
+/**
+ * arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
+ * @base: Physical base address
+ * @size: Size of region
+ *
+ * If PAT is available, this does nothing.  If PAT is unavailable, it
+ * attempts to add a WC MTRR covering size bytes starting at base and
+ * logs an error if this fails.
+ *
+ * Drivers must store the return value to pass to mtrr_del_wc_if_needed,
+ * but drivers should not try to interpret that return value.
+ */
+int arch_phys_wc_add(unsigned long base, unsigned long size)
+{
+	int ret;
+
+	if (pat_enabled)
+		return 0;  /* Success!  (We don't need to do anything.) */
+
+	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
+	if (ret < 0) {
+		pr_warn("Failed to add WC MTRR for [%p-%p]; performance may suffer.",
+			(void *)base, (void *)(base + size - 1));
+		return ret;
+	}
+	return ret + MTRR_TO_PHYS_WC_OFFSET;
+}
+EXPORT_SYMBOL(arch_phys_wc_add);
+
+/*
+ * arch_phys_wc_del - undoes arch_phys_wc_add
+ * @handle: Return value from arch_phys_wc_add
+ *
+ * This cleans up after mtrr_add_wc_if_needed.
+ *
+ * The API guarantees that mtrr_del_wc_if_needed(error code) and
+ * mtrr_del_wc_if_needed(0) do nothing.
+ */
+void arch_phys_wc_del(int handle)
+{
+	if (handle >= 1) {
+		WARN_ON(handle < MTRR_TO_PHYS_WC_OFFSET);
+		mtrr_del(handle - MTRR_TO_PHYS_WC_OFFSET, 0, 0);
+	}
+}
+EXPORT_SYMBOL(arch_phys_wc_del);
+
+/*
+ * phys_wc_to_mtrr_index - translates arch_phys_wc_add's return value
+ * @handle: Return value from arch_phys_wc_add
+ *
+ * This will turn the return value from arch_phys_wc_add into an mtrr
+ * index suitable for debugging.
+ *
+ * Note: There is no legitimate use for this function, except possibly
+ * in printk line.  Alas there is an illegitimate use in some ancient
+ * drm ioctls.
+ */
+int phys_wc_to_mtrr_index(int handle)
+{
+	if (handle < MTRR_TO_PHYS_WC_OFFSET)
+		return -1;
+	else
+		return handle - MTRR_TO_PHYS_WC_OFFSET;
+}
+EXPORT_SYMBOL_GPL(phys_wc_to_mtrr_index);
+
 /*
  * HACK ALERT!
  * These should be called implicitly, but we can't yet until all the initcall

+ 1 - 1
drivers/base/Makefile

@@ -10,7 +10,7 @@ obj-$(CONFIG_CMA) += dma-contiguous.o
 obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o
+obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o reservation.o
 obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o

+ 39 - 0
drivers/base/reservation.c

@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012-2013 Canonical Ltd
+ *
+ * Based on bo.c which bears the following copyright notice,
+ * but is dual licensed:
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <linux/reservation.h>
+#include <linux/export.h>
+
+DEFINE_WW_CLASS(reservation_ww_class);
+EXPORT_SYMBOL(reservation_ww_class);

+ 2 - 2
drivers/char/agp/ati-agp.c

@@ -236,14 +236,14 @@ static int ati_configure(void)
 static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
 {
 	pci_save_state(dev);
-	pci_set_power_state(dev, 3);
+	pci_set_power_state(dev, PCI_D3hot);
 
 	return 0;
 }
 
 static int agp_ati_resume(struct pci_dev *dev)
 {
-	pci_set_power_state(dev, 0);
+	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
 
 	return ati_configure();

+ 5 - 3
drivers/char/agp/frontend.c

@@ -603,7 +603,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (io_remap_pfn_range(vma, vma->vm_start,
 				(kerninfo.aper_base + offset) >> PAGE_SHIFT,
-					    size, vma->vm_page_prot)) {
+				size,
+				pgprot_writecombine(vma->vm_page_prot))) {
 			goto out_again;
 		}
 		mutex_unlock(&(agp_fe.agp_mutex));
@@ -618,8 +619,9 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (io_remap_pfn_range(vma, vma->vm_start,
-					    kerninfo.aper_base >> PAGE_SHIFT,
-					    size, vma->vm_page_prot)) {
+				kerninfo.aper_base >> PAGE_SHIFT,
+				size,
+				pgprot_writecombine(vma->vm_page_prot))) {
 			goto out_again;
 		}
 		mutex_unlock(&(agp_fe.agp_mutex));

+ 3 - 3
drivers/char/agp/nvidia-agp.c

@@ -399,8 +399,8 @@ static void agp_nvidia_remove(struct pci_dev *pdev)
 #ifdef CONFIG_PM
 static int agp_nvidia_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-	pci_save_state (pdev);
-	pci_set_power_state (pdev, 3);
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
 }
@@ -408,7 +408,7 @@ static int agp_nvidia_suspend(struct pci_dev *pdev, pm_message_t state)
 static int agp_nvidia_resume(struct pci_dev *pdev)
 {
 	/* set power state 0 and restore PCI space */
-	pci_set_power_state (pdev, 0);
+	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 
 	/* reconfigure AGP hardware again */

+ 3 - 0
drivers/gpu/drm/Kconfig

@@ -139,6 +139,7 @@ config DRM_I915
 	select BACKLIGHT_CLASS_DEVICE if ACPI
 	select VIDEO_OUTPUT_CONTROL if ACPI
 	select INPUT if ACPI
+	select THERMAL if ACPI
 	select ACPI_VIDEO if ACPI
 	select ACPI_BUTTON if ACPI
 	help
@@ -213,6 +214,8 @@ source "drivers/gpu/drm/mgag200/Kconfig"
 
 source "drivers/gpu/drm/cirrus/Kconfig"
 
+source "drivers/gpu/drm/rcar-du/Kconfig"
+
 source "drivers/gpu/drm/shmobile/Kconfig"
 
 source "drivers/gpu/drm/omapdrm/Kconfig"

+ 3 - 1
drivers/gpu/drm/Makefile

@@ -12,7 +12,8 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
-		drm_trace_points.o drm_global.o drm_prime.o
+		drm_trace_points.o drm_global.o drm_prime.o \
+		drm_rect.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -48,6 +49,7 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
+obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
 obj-$(CONFIG_DRM_TILCDC)	+= tilcdc/

+ 18 - 2
drivers/gpu/drm/ast/ast_drv.h

@@ -348,8 +348,24 @@ int ast_gem_create(struct drm_device *dev,
 int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr);
 int ast_bo_unpin(struct ast_bo *bo);
 
-int ast_bo_reserve(struct ast_bo *bo, bool no_wait);
-void ast_bo_unreserve(struct ast_bo *bo);
+static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
+{
+	int ret;
+
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+	if (ret) {
+		if (ret != -ERESTARTSYS && ret != -EBUSY)
+			DRM_ERROR("reserve failed %p\n", bo);
+		return ret;
+	}
+	return 0;
+}
+
+static inline void ast_bo_unreserve(struct ast_bo *bo)
+{
+	ttm_bo_unreserve(&bo->bo);
+}
+
 void ast_ttm_placement(struct ast_bo *bo, int domain);
 int ast_bo_push_sysram(struct ast_bo *bo);
 int ast_mmap(struct file *filp, struct vm_area_struct *vma);

+ 3 - 2
drivers/gpu/drm/ast/ast_fb.c

@@ -51,7 +51,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
 	struct ast_bo *bo;
 	int src_offset, dst_offset;
 	int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;
-	int ret;
+	int ret = -EBUSY;
 	bool unmap = false;
 	bool store_for_later = false;
 	int x2, y2;
@@ -65,7 +65,8 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
 	 * then the BO is being moved and we should
 	 * store up the damage until later.
 	 */
-	ret = ast_bo_reserve(bo, true);
+	if (!in_interrupt())
+		ret = ast_bo_reserve(bo, true);
 	if (ret) {
 		if (ret != -EBUSY)
 			return;

+ 3 - 28
drivers/gpu/drm/ast/ast_ttm.c

@@ -271,26 +271,19 @@ int ast_mm_init(struct ast_private *ast)
 		return ret;
 	}
 
-	ast->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
-				    pci_resource_len(dev->pdev, 0),
-				    DRM_MTRR_WC);
+	ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+					pci_resource_len(dev->pdev, 0));
 
 	return 0;
 }
 
 void ast_mm_fini(struct ast_private *ast)
 {
-	struct drm_device *dev = ast->dev;
 	ttm_bo_device_release(&ast->ttm.bdev);
 
 	ast_ttm_global_release(ast);
 
-	if (ast->fb_mtrr >= 0) {
-		drm_mtrr_del(ast->fb_mtrr,
-			     pci_resource_start(dev->pdev, 0),
-			     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
-		ast->fb_mtrr = -1;
-	}
+	arch_phys_wc_del(ast->fb_mtrr);
 }
 
 void ast_ttm_placement(struct ast_bo *bo, int domain)
@@ -310,24 +303,6 @@ void ast_ttm_placement(struct ast_bo *bo, int domain)
 	bo->placement.num_busy_placement = c;
 }
 
-int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
-{
-	int ret;
-
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
-	if (ret) {
-		if (ret != -ERESTARTSYS && ret != -EBUSY)
-			DRM_ERROR("reserve failed %p\n", bo);
-		return ret;
-	}
-	return 0;
-}
-
-void ast_bo_unreserve(struct ast_bo *bo)
-{
-	ttm_bo_unreserve(&bo->bo);
-}
-
 int ast_bo_create(struct drm_device *dev, int size, int align,
 		  uint32_t flags, struct ast_bo **pastbo)
 {

+ 19 - 2
drivers/gpu/drm/cirrus/cirrus_drv.h

@@ -240,8 +240,25 @@ void cirrus_ttm_placement(struct cirrus_bo *bo, int domain);
 int cirrus_bo_create(struct drm_device *dev, int size, int align,
 		     uint32_t flags, struct cirrus_bo **pcirrusbo);
 int cirrus_mmap(struct file *filp, struct vm_area_struct *vma);
-int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait);
-void cirrus_bo_unreserve(struct cirrus_bo *bo);
+
+static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
+{
+	int ret;
+
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+	if (ret) {
+		if (ret != -ERESTARTSYS && ret != -EBUSY)
+			DRM_ERROR("reserve failed %p\n", bo);
+		return ret;
+	}
+	return 0;
+}
+
+static inline void cirrus_bo_unreserve(struct cirrus_bo *bo)
+{
+	ttm_bo_unreserve(&bo->bo);
+}
+
 int cirrus_bo_push_sysram(struct cirrus_bo *bo);
 int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr);
 #endif				/* __CIRRUS_DRV_H__ */

+ 3 - 2
drivers/gpu/drm/cirrus/cirrus_fbdev.c

@@ -25,7 +25,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
 	struct cirrus_bo *bo;
 	int src_offset, dst_offset;
 	int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;
-	int ret;
+	int ret = -EBUSY;
 	bool unmap = false;
 	bool store_for_later = false;
 	int x2, y2;
@@ -39,7 +39,8 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
 	 * then the BO is being moved and we should
 	 * store up the damage until later.
 	 */
-	ret = cirrus_bo_reserve(bo, true);
+	if (!in_interrupt())
+		ret = cirrus_bo_reserve(bo, true);
 	if (ret) {
 		if (ret != -EBUSY)
 			return;

+ 4 - 29
drivers/gpu/drm/cirrus/cirrus_ttm.c

@@ -271,9 +271,8 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
 		return ret;
 	}
 
-	cirrus->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
-				    pci_resource_len(dev->pdev, 0),
-				    DRM_MTRR_WC);
+	cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
+					   pci_resource_len(dev->pdev, 0));
 
 	cirrus->mm_inited = true;
 	return 0;
@@ -281,8 +280,6 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
 
 void cirrus_mm_fini(struct cirrus_device *cirrus)
 {
-	struct drm_device *dev = cirrus->dev;
-
 	if (!cirrus->mm_inited)
 		return;
 
@@ -290,12 +287,8 @@ void cirrus_mm_fini(struct cirrus_device *cirrus)
 
 	cirrus_ttm_global_release(cirrus);
 
-	if (cirrus->fb_mtrr >= 0) {
-		drm_mtrr_del(cirrus->fb_mtrr,
-			     pci_resource_start(dev->pdev, 0),
-			     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
-		cirrus->fb_mtrr = -1;
-	}
+	arch_phys_wc_del(cirrus->fb_mtrr);
+	cirrus->fb_mtrr = 0;
 }
 
 void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
@@ -315,24 +308,6 @@ void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
 	bo->placement.num_busy_placement = c;
 }
 
-int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
-{
-	int ret;
-
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
-	if (ret) {
-		if (ret != -ERESTARTSYS && ret != -EBUSY)
-			DRM_ERROR("reserve failed %p\n", bo);
-		return ret;
-	}
-	return 0;
-}
-
-void cirrus_bo_unreserve(struct cirrus_bo *bo)
-{
-	ttm_bo_unreserve(&bo->bo);
-}
-
 int cirrus_bo_create(struct drm_device *dev, int size, int align,
 		  uint32_t flags, struct cirrus_bo **pcirrusbo)
 {

+ 18 - 8
drivers/gpu/drm/drm_bufs.c

@@ -210,12 +210,16 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 		if (drm_core_has_MTRR(dev)) {
 			if (map->type == _DRM_FRAME_BUFFER ||
 			    (map->flags & _DRM_WRITE_COMBINING)) {
-				map->mtrr = mtrr_add(map->offset, map->size,
-						     MTRR_TYPE_WRCOMB, 1);
+				map->mtrr =
+					arch_phys_wc_add(map->offset, map->size);
 			}
 		}
 		if (map->type == _DRM_REGISTERS) {
-			map->handle = ioremap(map->offset, map->size);
+			if (map->flags & _DRM_WRITE_COMBINING)
+				map->handle = ioremap_wc(map->offset,
+							 map->size);
+			else
+				map->handle = ioremap(map->offset, map->size);
 			if (!map->handle) {
 				kfree(map);
 				return -ENOMEM;
@@ -410,6 +414,15 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
 
 	/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
 	map->handle = (void *)(unsigned long)maplist->user_token;
+
+	/*
+	 * It appears that there are no users of this value whatsoever --
+	 * drmAddMap just discards it.  Let's not encourage its use.
+	 * (Keeping drm_addmap_core's returned mtrr value would be wrong --
+	 *  it's not a real mtrr index anymore.)
+	 */
+	map->mtrr = -1;
+
 	return 0;
 }
 
@@ -451,11 +464,8 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
 		iounmap(map->handle);
 		/* FALLTHROUGH */
 	case _DRM_FRAME_BUFFER:
-		if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-			int retcode;
-			retcode = mtrr_del(map->mtrr, map->offset, map->size);
-			DRM_DEBUG("mtrr_del=%d\n", retcode);
-		}
+		if (drm_core_has_MTRR(dev))
+			arch_phys_wc_del(map->mtrr);
 		break;
 	case _DRM_SHM:
 		vfree(map->handle);

+ 147 - 44
drivers/gpu/drm/drm_crtc.c

@@ -29,6 +29,7 @@
  *      Dave Airlie <airlied@linux.ie>
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
+#include <linux/ctype.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/export.h>
@@ -91,7 +92,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
 
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list)				\
-	char *fnname(int val)					\
+	const char *fnname(int val)				\
 	{							\
 		int i;						\
 		for (i = 0; i < ARRAY_SIZE(list); i++) {	\
@@ -104,7 +105,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
 /*
  * Global properties
  */
-static struct drm_prop_enum_list drm_dpms_enum_list[] =
+static const struct drm_prop_enum_list drm_dpms_enum_list[] =
 {	{ DRM_MODE_DPMS_ON, "On" },
 	{ DRM_MODE_DPMS_STANDBY, "Standby" },
 	{ DRM_MODE_DPMS_SUSPEND, "Suspend" },
@@ -116,7 +117,7 @@ DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
 /*
  * Optional properties
  */
-static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
+static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
 {
 	{ DRM_MODE_SCALE_NONE, "None" },
 	{ DRM_MODE_SCALE_FULLSCREEN, "Full" },
@@ -124,7 +125,7 @@ static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
 	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
 };
 
-static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
+static const struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
 {
 	{ DRM_MODE_DITHERING_OFF, "Off" },
 	{ DRM_MODE_DITHERING_ON, "On" },
@@ -134,7 +135,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
 /*
  * Non-global properties, but "required" for certain connectors.
  */
-static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
+static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
 {
 	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
@@ -143,7 +144,7 @@ static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
 
 DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
 
-static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
+static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
 {
 	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
@@ -153,7 +154,7 @@ static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
 		 drm_dvi_i_subconnector_enum_list)
 
-static struct drm_prop_enum_list drm_tv_select_enum_list[] =
+static const struct drm_prop_enum_list drm_tv_select_enum_list[] =
 {
 	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
@@ -164,7 +165,7 @@ static struct drm_prop_enum_list drm_tv_select_enum_list[] =
 
 DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
 
-static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
+static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
 {
 	{ DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
@@ -176,7 +177,7 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
-static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
+static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
 	{ DRM_MODE_DIRTY_OFF,      "Off"      },
 	{ DRM_MODE_DIRTY_ON,       "On"       },
 	{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
@@ -184,7 +185,7 @@ static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
 
 struct drm_conn_prop_enum_list {
 	int type;
-	char *name;
+	const char *name;
 	int count;
 };
 
@@ -210,7 +211,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
 	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
 };
 
-static struct drm_prop_enum_list drm_encoder_enum_list[] =
+static const struct drm_prop_enum_list drm_encoder_enum_list[] =
 {	{ DRM_MODE_ENCODER_NONE, "None" },
 	{ DRM_MODE_ENCODER_DAC, "DAC" },
 	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
@@ -219,7 +220,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
 	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 };
 
-char *drm_get_encoder_name(struct drm_encoder *encoder)
+const char *drm_get_encoder_name(const struct drm_encoder *encoder)
 {
 	static char buf[32];
 
@@ -230,7 +231,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_get_encoder_name);
 
-char *drm_get_connector_name(struct drm_connector *connector)
+const char *drm_get_connector_name(const struct drm_connector *connector)
 {
 	static char buf[32];
 
@@ -241,7 +242,7 @@ char *drm_get_connector_name(struct drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_get_connector_name);
 
-char *drm_get_connector_status_name(enum drm_connector_status status)
+const char *drm_get_connector_status_name(enum drm_connector_status status)
 {
 	if (status == connector_status_connected)
 		return "connected";
@@ -252,6 +253,28 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
 }
 EXPORT_SYMBOL(drm_get_connector_status_name);
 
+static char printable_char(int c)
+{
+	return isascii(c) && isprint(c) ? c : '?';
+}
+
+const char *drm_get_format_name(uint32_t format)
+{
+	static char buf[32];
+
+	snprintf(buf, sizeof(buf),
+		 "%c%c%c%c %s-endian (0x%08x)",
+		 printable_char(format & 0xff),
+		 printable_char((format >> 8) & 0xff),
+		 printable_char((format >> 16) & 0xff),
+		 printable_char((format >> 24) & 0x7f),
+		 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
+		 format);
+
+	return buf;
+}
+EXPORT_SYMBOL(drm_get_format_name);
+
 /**
  * drm_mode_object_get - allocate a new modeset identifier
  * @dev: DRM device
@@ -569,16 +592,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 		}
 
 		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-			if (plane->fb == fb) {
-				/* should turn off the crtc */
-				ret = plane->funcs->disable_plane(plane);
-				if (ret)
-					DRM_ERROR("failed to disable plane with busy fb\n");
-				/* disconnect the plane from the fb and crtc: */
-				__drm_framebuffer_unreference(plane->fb);
-				plane->fb = NULL;
-				plane->crtc = NULL;
-			}
+			if (plane->fb == fb)
+				drm_plane_force_disable(plane);
 		}
 		drm_modeset_unlock_all(dev);
 	}
@@ -593,7 +608,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
  * @crtc: CRTC object to init
  * @funcs: callbacks for the new CRTC
  *
- * Inits a new object created as base part of an driver crtc object.
+ * Inits a new object created as base part of a driver crtc object.
  *
  * RETURNS:
  * Zero on success, error code on failure.
@@ -628,11 +643,12 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 EXPORT_SYMBOL(drm_crtc_init);
 
 /**
- * drm_crtc_cleanup - Cleans up the core crtc usage.
+ * drm_crtc_cleanup - Clean up the core crtc usage
  * @crtc: CRTC to cleanup
  *
- * Cleanup @crtc. Removes from drm modesetting space
- * does NOT free object, caller does that.
+ * This function cleans up @crtc and removes it from the DRM mode setting
+ * core. Note that the function does *not* free the crtc structure itself,
+ * this is the responsibility of the caller.
  */
 void drm_crtc_cleanup(struct drm_crtc *crtc)
 {
@@ -657,7 +673,7 @@ EXPORT_SYMBOL(drm_crtc_cleanup);
 void drm_mode_probed_add(struct drm_connector *connector,
 			 struct drm_display_mode *mode)
 {
-	list_add(&mode->head, &connector->probed_modes);
+	list_add_tail(&mode->head, &connector->probed_modes);
 }
 EXPORT_SYMBOL(drm_mode_probed_add);
 
@@ -803,6 +819,21 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+/**
+ * drm_plane_init - Initialise a new plane object
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @format_count: number of elements in @formats
+ * @priv: plane is private (hidden from userspace)?
+ *
+ * Inits a new object created as base part of a driver plane object.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure.
+ */
 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		   unsigned long possible_crtcs,
 		   const struct drm_plane_funcs *funcs,
@@ -851,6 +882,14 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 }
 EXPORT_SYMBOL(drm_plane_init);
 
+/**
+ * drm_plane_cleanup - Clean up the core plane usage
+ * @plane: plane to cleanup
+ *
+ * This function cleans up @plane and removes it from the DRM mode setting
+ * core. Note that the function does *not* free the plane structure itself,
+ * this is the responsibility of the caller.
+ */
 void drm_plane_cleanup(struct drm_plane *plane)
 {
 	struct drm_device *dev = plane->dev;
@@ -867,6 +906,32 @@ void drm_plane_cleanup(struct drm_plane *plane)
 }
 EXPORT_SYMBOL(drm_plane_cleanup);
 
+/**
+ * drm_plane_force_disable - Forcibly disable a plane
+ * @plane: plane to disable
+ *
+ * Forces the plane to be disabled.
+ *
+ * Used when the plane's current framebuffer is destroyed,
+ * and when restoring fbdev mode.
+ */
+void drm_plane_force_disable(struct drm_plane *plane)
+{
+	int ret;
+
+	if (!plane->fb)
+		return;
+
+	ret = plane->funcs->disable_plane(plane);
+	if (ret)
+		DRM_ERROR("failed to disable plane with busy fb\n");
+	/* disconnect the plane from the fb and crtc: */
+	__drm_framebuffer_unreference(plane->fb);
+	plane->fb = NULL;
+	plane->crtc = NULL;
+}
+EXPORT_SYMBOL(drm_plane_force_disable);
+
 /**
  * drm_mode_create - create a new display mode
  * @dev: DRM device
@@ -1740,7 +1805,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 
 	plane_resp->plane_id = plane->base.id;
 	plane_resp->possible_crtcs = plane->possible_crtcs;
-	plane_resp->gamma_size = plane->gamma_size;
+	plane_resp->gamma_size = 0;
 
 	/*
 	 * This ioctl is called twice, once to determine how much space is
@@ -1834,7 +1899,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 		if (fb->pixel_format == plane->format_types[i])
 			break;
 	if (i == plane->format_count) {
-		DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
+		DRM_DEBUG_KMS("Invalid pixel format %s\n",
+			      drm_get_format_name(fb->pixel_format));
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1906,18 +1972,31 @@ out:
 int drm_mode_set_config_internal(struct drm_mode_set *set)
 {
 	struct drm_crtc *crtc = set->crtc;
-	struct drm_framebuffer *fb, *old_fb;
+	struct drm_framebuffer *fb;
+	struct drm_crtc *tmp;
 	int ret;
 
-	old_fb = crtc->fb;
+	/*
+	 * NOTE: ->set_config can also disable other crtcs (if we steal all
+	 * connectors from it), hence we need to refcount the fbs across all
+	 * crtcs. Atomic modeset will have saner semantics ...
+	 */
+	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
+		tmp->old_fb = tmp->fb;
+
 	fb = set->fb;
 
 	ret = crtc->funcs->set_config(set);
 	if (ret == 0) {
-		if (old_fb)
-			drm_framebuffer_unreference(old_fb);
-		if (fb)
-			drm_framebuffer_reference(fb);
+		/* crtc->fb must be updated by ->set_config, enforces this. */
+		WARN_ON(fb != crtc->fb);
+	}
+
+	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
+		if (tmp->fb)
+			drm_framebuffer_reference(tmp->fb);
+		if (tmp->old_fb)
+			drm_framebuffer_unreference(tmp->old_fb);
 	}
 
 	return ret;
@@ -2099,10 +2178,10 @@ out:
 	return ret;
 }
 
-int drm_mode_cursor_ioctl(struct drm_device *dev,
-			void *data, struct drm_file *file_priv)
+static int drm_mode_cursor_common(struct drm_device *dev,
+				  struct drm_mode_cursor2 *req,
+				  struct drm_file *file_priv)
 {
-	struct drm_mode_cursor *req = data;
 	struct drm_mode_object *obj;
 	struct drm_crtc *crtc;
 	int ret = 0;
@@ -2122,13 +2201,17 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
 
 	mutex_lock(&crtc->mutex);
 	if (req->flags & DRM_MODE_CURSOR_BO) {
-		if (!crtc->funcs->cursor_set) {
+		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
 			ret = -ENXIO;
 			goto out;
 		}
 		/* Turns off the cursor if handle is 0 */
-		ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
-					      req->width, req->height);
+		if (crtc->funcs->cursor_set2)
+			ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
+						      req->width, req->height, req->hot_x, req->hot_y);
+		else
+			ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
+						      req->width, req->height);
 	}
 
 	if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -2143,6 +2226,25 @@ out:
 	mutex_unlock(&crtc->mutex);
 
 	return ret;
+
+}
+int drm_mode_cursor_ioctl(struct drm_device *dev,
+			void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_cursor *req = data;
+	struct drm_mode_cursor2 new_req;
+
+	memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
+	new_req.hot_x = new_req.hot_y = 0;
+
+	return drm_mode_cursor_common(dev, &new_req, file_priv);
+}
+
+int drm_mode_cursor2_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_cursor2 *req = data;
+	return drm_mode_cursor_common(dev, req, file_priv);
 }
 
 /* Original addfb only supported RGB formats, so figure out which one */
@@ -2312,7 +2414,8 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
 
 	ret = format_check(r);
 	if (ret) {
-		DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
+		DRM_DEBUG_KMS("bad framebuffer format %s\n",
+			      drm_get_format_name(r->pixel_format));
 		return ret;
 	}
 

+ 25 - 20
drivers/gpu/drm/drm_crtc_helper.c

@@ -189,13 +189,14 @@ prune:
 	if (list_empty(&connector->modes))
 		return 0;
 
+	list_for_each_entry(mode, &connector->modes, head)
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
 	drm_mode_sort(&connector->modes);
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
 			drm_get_connector_name(connector));
 	list_for_each_entry(mode, &connector->modes, head) {
-		mode->vrefresh = drm_mode_vrefresh(mode);
-
 		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
 		drm_mode_debug_printmodeline(mode);
 	}
@@ -564,14 +565,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 
 	DRM_DEBUG_KMS("\n");
 
-	if (!set)
-		return -EINVAL;
-
-	if (!set->crtc)
-		return -EINVAL;
+	BUG_ON(!set);
+	BUG_ON(!set->crtc);
+	BUG_ON(!set->crtc->helper_private);
 
-	if (!set->crtc->helper_private)
-		return -EINVAL;
+	/* Enforce sane interface api - has been abused by the fb helper. */
+	BUG_ON(!set->mode && set->fb);
+	BUG_ON(set->fb && set->num_connectors == 0);
 
 	crtc_funcs = set->crtc->helper_private;
 
@@ -645,11 +645,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			mode_changed = true;
 		} else if (set->fb == NULL) {
 			mode_changed = true;
-		} else if (set->fb->depth != set->crtc->fb->depth) {
-			mode_changed = true;
-		} else if (set->fb->bits_per_pixel !=
-			   set->crtc->fb->bits_per_pixel) {
-			mode_changed = true;
 		} else if (set->fb->pixel_format !=
 			   set->crtc->fb->pixel_format) {
 			mode_changed = true;
@@ -759,12 +754,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 				ret = -EINVAL;
 				goto fail;
 			}
-			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
-			for (i = 0; i < set->num_connectors; i++) {
-				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
-					      drm_get_connector_name(set->connectors[i]));
-				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
-			}
 		}
 		drm_helper_disable_unused_functions(dev);
 	} else if (fb_changed) {
@@ -782,6 +771,22 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 		}
 	}
 
+	/*
+	 * crtc set_config helpers implicit set the crtc and all connected
+	 * encoders to DPMS on for a full mode set. But for just an fb update it
+	 * doesn't do that. To not confuse userspace, do an explicit DPMS_ON
+	 * unconditionally. This will also ensure driver internal dpms state is
+	 * consistent again.
+	 */
+	if (set->crtc->enabled) {
+		DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+		for (i = 0; i < set->num_connectors; i++) {
+			DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+				      drm_get_connector_name(set->connectors[i]));
+			set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
+		}
+	}
+
 	kfree(save_connectors);
 	kfree(save_encoders);
 	kfree(save_crtcs);

+ 1 - 0
drivers/gpu/drm/drm_drv.c

@@ -166,6 +166,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )

+ 96 - 19
drivers/gpu/drm/drm_edid.c

@@ -968,6 +968,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
 	u8 csum = 0;
 	struct edid *edid = (struct edid *)raw_edid;
 
+	if (WARN_ON(!raw_edid))
+		return false;
+
 	if (edid_fixup > 8 || edid_fixup < 0)
 		edid_fixup = 6;
 
@@ -1010,15 +1013,15 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
 		break;
 	}
 
-	return 1;
+	return true;
 
 bad:
-	if (raw_edid && print_bad_edid) {
+	if (print_bad_edid) {
 		printk(KERN_ERR "Raw EDID:\n");
 		print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
 			       raw_edid, EDID_LENGTH, false);
 	}
-	return 0;
+	return false;
 }
 EXPORT_SYMBOL(drm_edid_block_valid);
 
@@ -1706,11 +1709,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 		return NULL;
 
 	if (pt->misc & DRM_EDID_PT_STEREO) {
-		printk(KERN_WARNING "stereo mode not supported\n");
+		DRM_DEBUG_KMS("stereo mode not supported\n");
 		return NULL;
 	}
 	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
-		printk(KERN_WARNING "composite sync not supported\n");
+		DRM_DEBUG_KMS("composite sync not supported\n");
 	}
 
 	/* it is incorrect if hsync/vsync width is zero */
@@ -2321,6 +2324,31 @@ u8 *drm_find_cea_extension(struct edid *edid)
 }
 EXPORT_SYMBOL(drm_find_cea_extension);
 
+/*
+ * Calculate the alternate clock for the CEA mode
+ * (60Hz vs. 59.94Hz etc.)
+ */
+static unsigned int
+cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
+{
+	unsigned int clock = cea_mode->clock;
+
+	if (cea_mode->vrefresh % 6 != 0)
+		return clock;
+
+	/*
+	 * edid_cea_modes contains the 59.94Hz
+	 * variant for 240 and 480 line modes,
+	 * and the 60Hz variant otherwise.
+	 */
+	if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
+		clock = clock * 1001 / 1000;
+	else
+		clock = DIV_ROUND_UP(clock * 1000, 1001);
+
+	return clock;
+}
+
 /**
  * drm_match_cea_mode - look for a CEA mode matching given mode
  * @to_match: display mode
@@ -2339,21 +2367,9 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
 		const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
 		unsigned int clock1, clock2;
 
-		clock1 = clock2 = cea_mode->clock;
-
 		/* Check both 60Hz and 59.94Hz */
-		if (cea_mode->vrefresh % 6 == 0) {
-			/*
-			 * edid_cea_modes contains the 59.94Hz
-			 * variant for 240 and 480 line modes,
-			 * and the 60Hz variant otherwise.
-			 */
-			if (cea_mode->vdisplay == 240 ||
-			    cea_mode->vdisplay == 480)
-				clock1 = clock1 * 1001 / 1000;
-			else
-				clock2 = DIV_ROUND_UP(clock2 * 1000, 1001);
-		}
+		clock1 = cea_mode->clock;
+		clock2 = cea_mode_alternate_clock(cea_mode);
 
 		if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
 		     KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
@@ -2364,6 +2380,66 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
 }
 EXPORT_SYMBOL(drm_match_cea_mode);
 
+static int
+add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode, *tmp;
+	LIST_HEAD(list);
+	int modes = 0;
+
+	/* Don't add CEA modes if the CEA extension block is missing */
+	if (!drm_find_cea_extension(edid))
+		return 0;
+
+	/*
+	 * Go through all probed modes and create a new mode
+	 * with the alternate clock for certain CEA modes.
+	 */
+	list_for_each_entry(mode, &connector->probed_modes, head) {
+		const struct drm_display_mode *cea_mode;
+		struct drm_display_mode *newmode;
+		u8 cea_mode_idx = drm_match_cea_mode(mode) - 1;
+		unsigned int clock1, clock2;
+
+		if (cea_mode_idx >= ARRAY_SIZE(edid_cea_modes))
+			continue;
+
+		cea_mode = &edid_cea_modes[cea_mode_idx];
+
+		clock1 = cea_mode->clock;
+		clock2 = cea_mode_alternate_clock(cea_mode);
+
+		if (clock1 == clock2)
+			continue;
+
+		if (mode->clock != clock1 && mode->clock != clock2)
+			continue;
+
+		newmode = drm_mode_duplicate(dev, cea_mode);
+		if (!newmode)
+			continue;
+
+		/*
+		 * The current mode could be either variant. Make
+		 * sure to pick the "other" clock for the new mode.
+		 */
+		if (mode->clock != clock1)
+			newmode->clock = clock1;
+		else
+			newmode->clock = clock2;
+
+		list_add_tail(&newmode->head, &list);
+	}
+
+	list_for_each_entry_safe(mode, tmp, &list, head) {
+		list_del(&mode->head);
+		drm_mode_probed_add(connector, mode);
+		modes++;
+	}
+
+	return modes;
+}
 
 static int
 do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
@@ -2946,6 +3022,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
 		num_modes += add_inferred_modes(connector, edid);
 	num_modes += add_cea_modes(connector, edid);
+	num_modes += add_alternate_cea_modes(connector, edid);
 
 	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
 		edid_fixup_preferred(connector, quirks);

+ 1 - 2
drivers/gpu/drm/drm_edid_load.c

@@ -186,12 +186,11 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
 		goto relfw_out;
 	}
 
-	edid = kmalloc(fwsize, GFP_KERNEL);
+	edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
 	if (edid == NULL) {
 		err = -ENOMEM;
 		goto relfw_out;
 	}
-	memcpy(edid, fwdata, fwsize);
 
 	if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
 		connector->bad_edid_counter++;

+ 39 - 4
drivers/gpu/drm/drm_fb_helper.c

@@ -168,6 +168,9 @@ static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_h
 	uint16_t *r_base, *g_base, *b_base;
 	int i;
 
+	if (helper->funcs->gamma_get == NULL)
+		return;
+
 	r_base = crtc->gamma_store;
 	g_base = r_base + crtc->gamma_size;
 	b_base = g_base + crtc->gamma_size;
@@ -284,13 +287,27 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave);
  */
 bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 {
+	struct drm_device *dev = fb_helper->dev;
+	struct drm_plane *plane;
 	bool error = false;
-	int i, ret;
+	int i;
+
+	drm_warn_on_modeset_not_all_locked(dev);
 
-	drm_warn_on_modeset_not_all_locked(fb_helper->dev);
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
+		drm_plane_force_disable(plane);
 
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+		struct drm_crtc *crtc = mode_set->crtc;
+		int ret;
+
+		if (crtc->funcs->cursor_set) {
+			ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
+			if (ret)
+				error = true;
+		}
+
 		ret = drm_mode_set_config_internal(mode_set);
 		if (ret)
 			error = true;
@@ -583,6 +600,14 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 		return 0;
 	}
 
+	/*
+	 * The driver really shouldn't advertise pseudo/directcolor
+	 * visuals if it can't deal with the palette.
+	 */
+	if (WARN_ON(!fb_helper->funcs->gamma_set ||
+		    !fb_helper->funcs->gamma_get))
+		return -EINVAL;
+
 	pindex = regno;
 
 	if (fb->bits_per_pixel == 16) {
@@ -626,12 +651,19 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
 {
 	struct drm_fb_helper *fb_helper = info->par;
+	struct drm_device *dev = fb_helper->dev;
 	struct drm_crtc_helper_funcs *crtc_funcs;
 	u16 *red, *green, *blue, *transp;
 	struct drm_crtc *crtc;
 	int i, j, rc = 0;
 	int start;
 
+	drm_modeset_lock_all(dev);
+	if (!drm_fb_helper_is_bound(fb_helper)) {
+		drm_modeset_unlock_all(dev);
+		return -EBUSY;
+	}
+
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		crtc = fb_helper->crtc_info[i].mode_set.crtc;
 		crtc_funcs = crtc->helper_private;
@@ -654,10 +686,13 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
 
 			rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
 			if (rc)
-				return rc;
+				goto out;
 		}
-		crtc_funcs->load_lut(crtc);
+		if (crtc_funcs->load_lut)
+			crtc_funcs->load_lut(crtc);
 	}
+ out:
+	drm_modeset_unlock_all(dev);
 	return rc;
 }
 EXPORT_SYMBOL(drm_fb_helper_setcmap);

+ 20 - 5
drivers/gpu/drm/drm_fops.c

@@ -271,6 +271,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 	priv->uid = current_euid();
 	priv->pid = get_pid(task_pid(current));
 	priv->minor = idr_find(&drm_minors_idr, minor_id);
+	if (!priv->minor) {
+		ret = -ENODEV;
+		goto out_put_pid;
+	}
+
 	priv->ioctl_count = 0;
 	/* for compatibility root is always authenticated */
 	priv->authenticated = capable(CAP_SYS_ADMIN);
@@ -292,7 +297,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 	if (dev->driver->open) {
 		ret = dev->driver->open(dev, priv);
 		if (ret < 0)
-			goto out_free;
+			goto out_prime_destroy;
 	}
 
 
@@ -304,7 +309,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 		if (!priv->minor->master) {
 			mutex_unlock(&dev->struct_mutex);
 			ret = -ENOMEM;
-			goto out_free;
+			goto out_close;
 		}
 
 		priv->is_master = 1;
@@ -322,7 +327,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 				drm_master_put(&priv->minor->master);
 				drm_master_put(&priv->master);
 				mutex_unlock(&dev->struct_mutex);
-				goto out_free;
+				goto out_close;
 			}
 		}
 		mutex_lock(&dev->struct_mutex);
@@ -333,7 +338,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 				drm_master_put(&priv->minor->master);
 				drm_master_put(&priv->master);
 				mutex_unlock(&dev->struct_mutex);
-				goto out_free;
+				goto out_close;
 			}
 		}
 		mutex_unlock(&dev->struct_mutex);
@@ -367,7 +372,17 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 #endif
 
 	return 0;
-      out_free:
+
+out_close:
+	if (dev->driver->postclose)
+		dev->driver->postclose(dev, priv);
+out_prime_destroy:
+	if (drm_core_check_feature(dev, DRIVER_PRIME))
+		drm_prime_destroy_file_private(&priv->prime);
+	if (dev->driver->driver_features & DRIVER_GEM)
+		drm_gem_release(dev, priv);
+out_put_pid:
+	put_pid(priv->pid);
 	kfree(priv);
 	filp->private_data = NULL;
 	return ret;

+ 65 - 48
drivers/gpu/drm/drm_gem.c

@@ -108,12 +108,8 @@ drm_gem_init(struct drm_device *dev)
 		return -ENOMEM;
 	}
 
-	if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
-			DRM_FILE_PAGE_OFFSET_SIZE)) {
-		drm_ht_remove(&mm->offset_hash);
-		kfree(mm);
-		return -ENOMEM;
-	}
+	drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
+		    DRM_FILE_PAGE_OFFSET_SIZE);
 
 	return 0;
 }
@@ -453,25 +449,21 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
 	spin_lock(&dev->object_name_lock);
 	if (!obj->name) {
 		ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
-		obj->name = ret;
-		args->name = (uint64_t) obj->name;
-		spin_unlock(&dev->object_name_lock);
-		idr_preload_end();
-
 		if (ret < 0)
 			goto err;
-		ret = 0;
+
+		obj->name = ret;
 
 		/* Allocate a reference for the name table.  */
 		drm_gem_object_reference(obj);
-	} else {
-		args->name = (uint64_t) obj->name;
-		spin_unlock(&dev->object_name_lock);
-		idr_preload_end();
-		ret = 0;
 	}
 
+	args->name = (uint64_t) obj->name;
+	ret = 0;
+
 err:
+	spin_unlock(&dev->object_name_lock);
+	idr_preload_end();
 	drm_gem_object_unreference_unlocked(obj);
 	return ret;
 }
@@ -644,6 +636,59 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
+/**
+ * drm_gem_mmap_obj - memory map a GEM object
+ * @obj: the GEM object to map
+ * @obj_size: the object size to be mapped, in bytes
+ * @vma: VMA for the area to be mapped
+ *
+ * Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops
+ * provided by the driver. Depending on their requirements, drivers can either
+ * provide a fault handler in their gem_vm_ops (in which case any accesses to
+ * the object will be trapped, to perform migration, GTT binding, surface
+ * register allocation, or performance monitoring), or mmap the buffer memory
+ * synchronously after calling drm_gem_mmap_obj.
+ *
+ * This function is mainly intended to implement the DMABUF mmap operation, when
+ * the GEM object is not looked up based on its fake offset. To implement the
+ * DRM mmap operation, drivers should use the drm_gem_mmap() function.
+ *
+ * NOTE: This function has to be protected with dev->struct_mutex
+ *
+ * Return 0 or success or -EINVAL if the object size is smaller than the VMA
+ * size, or if no gem_vm_ops are provided.
+ */
+int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
+		     struct vm_area_struct *vma)
+{
+	struct drm_device *dev = obj->dev;
+
+	lockdep_assert_held(&dev->struct_mutex);
+
+	/* Check for valid size. */
+	if (obj_size < vma->vm_end - vma->vm_start)
+		return -EINVAL;
+
+	if (!dev->driver->gem_vm_ops)
+		return -EINVAL;
+
+	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_ops = dev->driver->gem_vm_ops;
+	vma->vm_private_data = obj;
+	vma->vm_page_prot =  pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+
+	/* Take a ref for this mapping of the object, so that the fault
+	 * handler can dereference the mmap offset's pointer to the object.
+	 * This reference is cleaned up by the corresponding vm_close
+	 * (which should happen whether the vma was created by this call, or
+	 * by a vm_open due to mremap or partial unmap or whatever).
+	 */
+	drm_gem_object_reference(obj);
+
+	drm_vm_open_locked(dev, vma);
+	return 0;
+}
+EXPORT_SYMBOL(drm_gem_mmap_obj);
 
 /**
  * drm_gem_mmap - memory map routine for GEM objects
@@ -653,11 +698,9 @@ EXPORT_SYMBOL(drm_gem_vm_close);
  * If a driver supports GEM object mapping, mmap calls on the DRM file
  * descriptor will end up here.
  *
- * If we find the object based on the offset passed in (vma->vm_pgoff will
+ * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
  * contain the fake offset we created when the GTT map ioctl was called on
- * the object), we set up the driver fault handler so that any accesses
- * to the object can be trapped, to perform migration, GTT binding, surface
- * register allocation, or performance monitoring.
+ * the object) and map it with a call to drm_gem_mmap_obj().
  */
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
@@ -665,7 +708,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 	struct drm_device *dev = priv->minor->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
 	struct drm_local_map *map = NULL;
-	struct drm_gem_object *obj;
 	struct drm_hash_item *hash;
 	int ret = 0;
 
@@ -686,32 +728,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 		goto out_unlock;
 	}
 
-	/* Check for valid size. */
-	if (map->size < vma->vm_end - vma->vm_start) {
-		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	obj = map->handle;
-	if (!obj->dev->driver->gem_vm_ops) {
-		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_ops = obj->dev->driver->gem_vm_ops;
-	vma->vm_private_data = map->handle;
-	vma->vm_page_prot =  pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-
-	/* Take a ref for this mapping of the object, so that the fault
-	 * handler can dereference the mmap offset's pointer to the object.
-	 * This reference is cleaned up by the corresponding vm_close
-	 * (which should happen whether the vma was created by this call, or
-	 * by a vm_open due to mremap or partial unmap or whatever).
-	 */
-	drm_gem_object_reference(obj);
-
-	drm_vm_open_locked(dev, vma);
+	ret = drm_gem_mmap_obj(map->handle, map->size, vma);
 
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);

+ 165 - 40
drivers/gpu/drm/drm_gem_cma_helper.c

@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
+#include <linux/dma-buf.h>
 #include <linux/dma-mapping.h>
 
 #include <drm/drmP.h>
@@ -32,11 +33,44 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
 	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
 }
 
-static void drm_gem_cma_buf_destroy(struct drm_device *drm,
-		struct drm_gem_cma_object *cma_obj)
+/*
+ * __drm_gem_cma_create - Create a GEM CMA object without allocating memory
+ * @drm: The drm device
+ * @size: The GEM object size
+ *
+ * This function creates and initializes a GEM CMA object of the given size, but
+ * doesn't allocate any memory to back the object.
+ *
+ * Return a struct drm_gem_cma_object* on success or ERR_PTR values on failure.
+ */
+static struct drm_gem_cma_object *
+__drm_gem_cma_create(struct drm_device *drm, unsigned int size)
 {
-	dma_free_writecombine(drm->dev, cma_obj->base.size, cma_obj->vaddr,
-			cma_obj->paddr);
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	int ret;
+
+	cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+	if (!cma_obj)
+		return ERR_PTR(-ENOMEM);
+
+	gem_obj = &cma_obj->base;
+
+	ret = drm_gem_object_init(drm, gem_obj, size);
+	if (ret)
+		goto error;
+
+	ret = drm_gem_create_mmap_offset(gem_obj);
+	if (ret) {
+		drm_gem_object_release(gem_obj);
+		goto error;
+	}
+
+	return cma_obj;
+
+error:
+	kfree(cma_obj);
+	return ERR_PTR(ret);
 }
 
 /*
@@ -49,44 +83,42 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
 		unsigned int size)
 {
 	struct drm_gem_cma_object *cma_obj;
-	struct drm_gem_object *gem_obj;
+	struct sg_table *sgt = NULL;
 	int ret;
 
 	size = round_up(size, PAGE_SIZE);
 
-	cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
-	if (!cma_obj)
-		return ERR_PTR(-ENOMEM);
+	cma_obj = __drm_gem_cma_create(drm, size);
+	if (IS_ERR(cma_obj))
+		return cma_obj;
 
 	cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
 			&cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN);
 	if (!cma_obj->vaddr) {
-		dev_err(drm->dev, "failed to allocate buffer with size %d\n", size);
+		dev_err(drm->dev, "failed to allocate buffer with size %d\n",
+			size);
 		ret = -ENOMEM;
-		goto err_dma_alloc;
+		goto error;
 	}
 
-	gem_obj = &cma_obj->base;
+	sgt = kzalloc(sizeof(*cma_obj->sgt), GFP_KERNEL);
+	if (sgt == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
 
-	ret = drm_gem_object_init(drm, gem_obj, size);
-	if (ret)
-		goto err_obj_init;
+	ret = dma_get_sgtable(drm->dev, sgt, cma_obj->vaddr,
+			      cma_obj->paddr, size);
+	if (ret < 0)
+		goto error;
 
-	ret = drm_gem_create_mmap_offset(gem_obj);
-	if (ret)
-		goto err_create_mmap_offset;
+	cma_obj->sgt = sgt;
 
 	return cma_obj;
 
-err_create_mmap_offset:
-	drm_gem_object_release(gem_obj);
-
-err_obj_init:
-	drm_gem_cma_buf_destroy(drm, cma_obj);
-
-err_dma_alloc:
-	kfree(cma_obj);
-
+error:
+	kfree(sgt);
+	drm_gem_cma_free_object(&cma_obj->base);
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
@@ -143,11 +175,20 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
 	if (gem_obj->map_list.map)
 		drm_gem_free_mmap_offset(gem_obj);
 
-	drm_gem_object_release(gem_obj);
-
 	cma_obj = to_drm_gem_cma_obj(gem_obj);
 
-	drm_gem_cma_buf_destroy(gem_obj->dev, cma_obj);
+	if (cma_obj->vaddr) {
+		dma_free_writecombine(gem_obj->dev->dev, cma_obj->base.size,
+				      cma_obj->vaddr, cma_obj->paddr);
+		if (cma_obj->sgt) {
+			sg_free_table(cma_obj->sgt);
+			kfree(cma_obj->sgt);
+		}
+	} else if (gem_obj->import_attach) {
+		drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
+	}
+
+	drm_gem_object_release(gem_obj);
 
 	kfree(cma_obj);
 }
@@ -174,10 +215,7 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
 
 	cma_obj = drm_gem_cma_create_with_handle(file_priv, dev,
 			args->size, &args->handle);
-	if (IS_ERR(cma_obj))
-		return PTR_ERR(cma_obj);
-
-	return 0;
+	return PTR_RET(cma_obj);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
 
@@ -215,13 +253,26 @@ const struct vm_operations_struct drm_gem_cma_vm_ops = {
 };
 EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
 
+static int drm_gem_cma_mmap_obj(struct drm_gem_cma_object *cma_obj,
+				struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT,
+			vma->vm_end - vma->vm_start, vma->vm_page_prot);
+	if (ret)
+		drm_gem_vm_close(vma);
+
+	return ret;
+}
+
 /*
  * drm_gem_cma_mmap - (struct file_operation)->mmap callback function
  */
 int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-	struct drm_gem_object *gem_obj;
 	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
 	int ret;
 
 	ret = drm_gem_mmap(filp, vma);
@@ -231,12 +282,7 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
 	gem_obj = vma->vm_private_data;
 	cma_obj = to_drm_gem_cma_obj(gem_obj);
 
-	ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT,
-			vma->vm_end - vma->vm_start, vma->vm_page_prot);
-	if (ret)
-		drm_gem_vm_close(vma);
-
-	return ret;
+	return drm_gem_cma_mmap_obj(cma_obj, vma);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
 
@@ -270,3 +316,82 @@ void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
 #endif
+
+/* low-level interface prime helpers */
+struct sg_table *drm_gem_cma_prime_get_sg_table(struct drm_gem_object *obj)
+{
+	struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
+	struct sg_table *sgt;
+	int ret;
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return NULL;
+
+	ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr,
+			      cma_obj->paddr, obj->size);
+	if (ret < 0)
+		goto out;
+
+	return sgt;
+
+out:
+	kfree(sgt);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_prime_get_sg_table);
+
+struct drm_gem_object *
+drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size,
+				  struct sg_table *sgt)
+{
+	struct drm_gem_cma_object *cma_obj;
+
+	if (sgt->nents != 1)
+		return ERR_PTR(-EINVAL);
+
+	/* Create a CMA GEM buffer. */
+	cma_obj = __drm_gem_cma_create(dev, size);
+	if (IS_ERR(cma_obj))
+		return ERR_PTR(PTR_ERR(cma_obj));
+
+	cma_obj->paddr = sg_dma_address(sgt->sgl);
+	cma_obj->sgt = sgt;
+
+	DRM_DEBUG_PRIME("dma_addr = 0x%x, size = %zu\n", cma_obj->paddr, size);
+
+	return &cma_obj->base;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table);
+
+int drm_gem_cma_prime_mmap(struct drm_gem_object *obj,
+			   struct vm_area_struct *vma)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_device *dev = obj->dev;
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = drm_gem_mmap_obj(obj, obj->size, vma);
+	mutex_unlock(&dev->struct_mutex);
+	if (ret < 0)
+		return ret;
+
+	cma_obj = to_drm_gem_cma_obj(obj);
+	return drm_gem_cma_mmap_obj(cma_obj, vma);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_prime_mmap);
+
+void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj)
+{
+	struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
+
+	return cma_obj->vaddr;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vmap);
+
+void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap);

+ 14 - 1
drivers/gpu/drm/drm_ioctl.c

@@ -38,6 +38,9 @@
 
 #include <linux/pci.h>
 #include <linux/export.h>
+#ifdef CONFIG_X86
+#include <asm/mtrr.h>
+#endif
 
 /**
  * Get the bus id.
@@ -181,7 +184,17 @@ int drm_getmap(struct drm_device *dev, void *data,
 	map->type = r_list->map->type;
 	map->flags = r_list->map->flags;
 	map->handle = (void *)(unsigned long) r_list->user_token;
-	map->mtrr = r_list->map->mtrr;
+
+#ifdef CONFIG_X86
+	/*
+	 * There appears to be exactly one user of the mtrr index: dritest.
+	 * It's easy enough to keep it working on non-PAT systems.
+	 */
+	map->mtrr = phys_wc_to_mtrr_index(r_list->map->mtrr);
+#else
+	map->mtrr = -1;
+#endif
+
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;

+ 22 - 23
drivers/gpu/drm/drm_mm.c

@@ -669,7 +669,7 @@ int drm_mm_clean(struct drm_mm * mm)
 }
 EXPORT_SYMBOL(drm_mm_clean);
 
-int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
+void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 	INIT_LIST_HEAD(&mm->hole_stack);
 	INIT_LIST_HEAD(&mm->unused_nodes);
@@ -690,8 +690,6 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 	list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
 
 	mm->color_adjust = NULL;
-
-	return 0;
 }
 EXPORT_SYMBOL(drm_mm_init);
 
@@ -699,8 +697,8 @@ void drm_mm_takedown(struct drm_mm * mm)
 {
 	struct drm_mm_node *entry, *next;
 
-	if (!list_empty(&mm->head_node.node_list)) {
-		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
+	if (WARN(!list_empty(&mm->head_node.node_list),
+		 "Memory manager not clean. Delaying takedown\n")) {
 		return;
 	}
 
@@ -716,36 +714,37 @@ void drm_mm_takedown(struct drm_mm * mm)
 }
 EXPORT_SYMBOL(drm_mm_takedown);
 
-void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
+static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
+				       const char *prefix)
 {
-	struct drm_mm_node *entry;
-	unsigned long total_used = 0, total_free = 0, total = 0;
 	unsigned long hole_start, hole_end, hole_size;
 
-	hole_start = drm_mm_hole_node_start(&mm->head_node);
-	hole_end = drm_mm_hole_node_end(&mm->head_node);
-	hole_size = hole_end - hole_start;
-	if (hole_size)
+	if (entry->hole_follows) {
+		hole_start = drm_mm_hole_node_start(entry);
+		hole_end = drm_mm_hole_node_end(entry);
+		hole_size = hole_end - hole_start;
 		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
 			prefix, hole_start, hole_end,
 			hole_size);
-	total_free += hole_size;
+		return hole_size;
+	}
+
+	return 0;
+}
+
+void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
+{
+	struct drm_mm_node *entry;
+	unsigned long total_used = 0, total_free = 0, total = 0;
+
+	total_free += drm_mm_debug_hole(&mm->head_node, prefix);
 
 	drm_mm_for_each_node(entry, mm) {
 		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
 			prefix, entry->start, entry->start + entry->size,
 			entry->size);
 		total_used += entry->size;
-
-		if (entry->hole_follows) {
-			hole_start = drm_mm_hole_node_start(entry);
-			hole_end = drm_mm_hole_node_end(entry);
-			hole_size = hole_end - hole_start;
-			printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
-				prefix, hole_start, hole_end,
-				hole_size);
-			total_free += hole_size;
-		}
+		total_free += drm_mm_debug_hole(entry, prefix);
 	}
 	total = total_free + total_used;
 

+ 11 - 3
drivers/gpu/drm/drm_modes.c

@@ -535,6 +535,8 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
 		dmode->flags |= DRM_MODE_FLAG_INTERLACE;
 	if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
 		dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+	if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
+		dmode->flags |= DRM_MODE_FLAG_DBLCLK;
 	drm_mode_set_name(dmode);
 
 	return 0;
@@ -787,16 +789,17 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  * LOCKING:
  * None.
  *
- * Copy an existing mode into another mode, preserving the object id
- * of the destination mode.
+ * Copy an existing mode into another mode, preserving the object id and
+ * list head of the destination mode.
  */
 void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
 {
 	int id = dst->base.id;
+	struct list_head head = dst->head;
 
 	*dst = *src;
 	dst->base.id = id;
-	INIT_LIST_HEAD(&dst->head);
+	dst->head = head;
 }
 EXPORT_SYMBOL(drm_mode_copy);
 
@@ -1017,6 +1020,11 @@ static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head
 	diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
 	if (diff)
 		return diff;
+
+	diff = b->vrefresh - a->vrefresh;
+	if (diff)
+		return diff;
+
 	diff = b->clock - a->clock;
 	return diff;
 }

+ 4 - 4
drivers/gpu/drm/drm_pci.c

@@ -278,10 +278,10 @@ static int drm_pci_agp_init(struct drm_device *dev)
 		}
 		if (drm_core_has_MTRR(dev)) {
 			if (dev->agp)
-				dev->agp->agp_mtrr =
-					mtrr_add(dev->agp->agp_info.aper_base,
-						 dev->agp->agp_info.aper_size *
-						 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+				dev->agp->agp_mtrr = arch_phys_wc_add(
+					dev->agp->agp_info.aper_base,
+					dev->agp->agp_info.aper_size *
+					1024 * 1024);
 		}
 	}
 	return 0;

+ 146 - 42
drivers/gpu/drm/drm_prime.c

@@ -62,20 +62,125 @@ struct drm_prime_member {
 	struct dma_buf *dma_buf;
 	uint32_t handle;
 };
-static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
+
+struct drm_prime_attachment {
+	struct sg_table *sgt;
+	enum dma_data_direction dir;
+};
+
+static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+{
+	struct drm_prime_member *member;
+
+	member = kmalloc(sizeof(*member), GFP_KERNEL);
+	if (!member)
+		return -ENOMEM;
+
+	get_dma_buf(dma_buf);
+	member->dma_buf = dma_buf;
+	member->handle = handle;
+	list_add(&member->entry, &prime_fpriv->head);
+	return 0;
+}
+
+static int drm_gem_map_attach(struct dma_buf *dma_buf,
+			      struct device *target_dev,
+			      struct dma_buf_attachment *attach)
+{
+	struct drm_prime_attachment *prime_attach;
+	struct drm_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->dev;
+
+	prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
+	if (!prime_attach)
+		return -ENOMEM;
+
+	prime_attach->dir = DMA_NONE;
+	attach->priv = prime_attach;
+
+	if (!dev->driver->gem_prime_pin)
+		return 0;
+
+	return dev->driver->gem_prime_pin(obj);
+}
+
+static void drm_gem_map_detach(struct dma_buf *dma_buf,
+			       struct dma_buf_attachment *attach)
+{
+	struct drm_prime_attachment *prime_attach = attach->priv;
+	struct drm_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->dev;
+	struct sg_table *sgt;
+
+	if (dev->driver->gem_prime_unpin)
+		dev->driver->gem_prime_unpin(obj);
+
+	if (!prime_attach)
+		return;
+
+	sgt = prime_attach->sgt;
+	if (sgt) {
+		if (prime_attach->dir != DMA_NONE)
+			dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
+					prime_attach->dir);
+		sg_free_table(sgt);
+	}
+
+	kfree(sgt);
+	kfree(prime_attach);
+	attach->priv = NULL;
+}
+
+static void drm_prime_remove_buf_handle_locked(
+		struct drm_prime_file_private *prime_fpriv,
+		struct dma_buf *dma_buf)
+{
+	struct drm_prime_member *member, *safe;
+
+	list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
+		if (member->dma_buf == dma_buf) {
+			dma_buf_put(dma_buf);
+			list_del(&member->entry);
+			kfree(member);
+		}
+	}
+}
 
 static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
 		enum dma_data_direction dir)
 {
+	struct drm_prime_attachment *prime_attach = attach->priv;
 	struct drm_gem_object *obj = attach->dmabuf->priv;
 	struct sg_table *sgt;
 
+	if (WARN_ON(dir == DMA_NONE || !prime_attach))
+		return ERR_PTR(-EINVAL);
+
+	/* return the cached mapping when possible */
+	if (prime_attach->dir == dir)
+		return prime_attach->sgt;
+
+	/*
+	 * two mappings with different directions for the same attachment are
+	 * not allowed
+	 */
+	if (WARN_ON(prime_attach->dir != DMA_NONE))
+		return ERR_PTR(-EBUSY);
+
 	mutex_lock(&obj->dev->struct_mutex);
 
 	sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
 
-	if (!IS_ERR_OR_NULL(sgt))
-		dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+	if (!IS_ERR(sgt)) {
+		if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) {
+			sg_free_table(sgt);
+			kfree(sgt);
+			sgt = ERR_PTR(-ENOMEM);
+		} else {
+			prime_attach->sgt = sgt;
+			prime_attach->dir = dir;
+		}
+	}
 
 	mutex_unlock(&obj->dev->struct_mutex);
 	return sgt;
@@ -84,9 +189,7 @@ static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
 static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
 		struct sg_table *sgt, enum dma_data_direction dir)
 {
-	dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
-	sg_free_table(sgt);
-	kfree(sgt);
+	/* nothing to be done here */
 }
 
 static void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
@@ -142,10 +245,18 @@ static void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
 static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf,
 		struct vm_area_struct *vma)
 {
-	return -EINVAL;
+	struct drm_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->dev;
+
+	if (!dev->driver->gem_prime_mmap)
+		return -ENOSYS;
+
+	return dev->driver->gem_prime_mmap(obj, vma);
 }
 
 static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
+	.attach = drm_gem_map_attach,
+	.detach = drm_gem_map_detach,
 	.map_dma_buf = drm_gem_map_dma_buf,
 	.unmap_dma_buf = drm_gem_unmap_dma_buf,
 	.release = drm_gem_dmabuf_release,
@@ -185,11 +296,6 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
 struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
 				     struct drm_gem_object *obj, int flags)
 {
-	if (dev->driver->gem_prime_pin) {
-		int ret = dev->driver->gem_prime_pin(obj);
-		if (ret)
-			return ERR_PTR(ret);
-	}
 	return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags);
 }
 EXPORT_SYMBOL(drm_gem_prime_export);
@@ -235,15 +341,34 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
 	ret = drm_prime_add_buf_handle(&file_priv->prime,
 				       obj->export_dma_buf, handle);
 	if (ret)
-		goto out;
+		goto fail_put_dmabuf;
+
+	ret = dma_buf_fd(buf, flags);
+	if (ret < 0)
+		goto fail_rm_handle;
 
-	*prime_fd = dma_buf_fd(buf, flags);
+	*prime_fd = ret;
 	mutex_unlock(&file_priv->prime.lock);
 	return 0;
 
 out_have_obj:
 	get_dma_buf(dmabuf);
-	*prime_fd = dma_buf_fd(dmabuf, flags);
+	ret = dma_buf_fd(dmabuf, flags);
+	if (ret < 0) {
+		dma_buf_put(dmabuf);
+	} else {
+		*prime_fd = ret;
+		ret = 0;
+	}
+
+	goto out;
+
+fail_rm_handle:
+	drm_prime_remove_buf_handle_locked(&file_priv->prime, buf);
+fail_put_dmabuf:
+	/* clear NOT to be checked when releasing dma_buf */
+	obj->export_dma_buf = NULL;
+	dma_buf_put(buf);
 out:
 	drm_gem_object_unreference_unlocked(obj);
 	mutex_unlock(&file_priv->prime.lock);
@@ -276,7 +401,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
 
 	attach = dma_buf_attach(dma_buf, dev->dev);
 	if (IS_ERR(attach))
-		return ERR_PTR(PTR_ERR(attach));
+		return ERR_CAST(attach);
 
 	get_dma_buf(dma_buf);
 
@@ -412,8 +537,10 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
 	int ret;
 
 	sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-	if (!sg)
+	if (!sg) {
+		ret = -ENOMEM;
 		goto out;
+	}
 
 	ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
 				nr_pages << PAGE_SHIFT, GFP_KERNEL);
@@ -423,7 +550,7 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
 	return sg;
 out:
 	kfree(sg);
-	return NULL;
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(drm_prime_pages_to_sg);
 
@@ -492,21 +619,6 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
 }
 EXPORT_SYMBOL(drm_prime_destroy_file_private);
 
-static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
-{
-	struct drm_prime_member *member;
-
-	member = kmalloc(sizeof(*member), GFP_KERNEL);
-	if (!member)
-		return -ENOMEM;
-
-	get_dma_buf(dma_buf);
-	member->dma_buf = dma_buf;
-	member->handle = handle;
-	list_add(&member->entry, &prime_fpriv->head);
-	return 0;
-}
-
 int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
 {
 	struct drm_prime_member *member;
@@ -523,16 +635,8 @@ EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
 
 void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
 {
-	struct drm_prime_member *member, *safe;
-
 	mutex_lock(&prime_fpriv->lock);
-	list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
-		if (member->dma_buf == dma_buf) {
-			dma_buf_put(dma_buf);
-			list_del(&member->entry);
-			kfree(member);
-		}
-	}
+	drm_prime_remove_buf_handle_locked(prime_fpriv, dma_buf);
 	mutex_unlock(&prime_fpriv->lock);
 }
 EXPORT_SYMBOL(drm_prime_remove_buf_handle);

+ 295 - 0
drivers/gpu/drm/drm_rect.c

@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2011-2013 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <drm/drmP.h>
+#include <drm/drm_rect.h>
+
+/**
+ * drm_rect_intersect - intersect two rectangles
+ * @r1: first rectangle
+ * @r2: second rectangle
+ *
+ * Calculate the intersection of rectangles @r1 and @r2.
+ * @r1 will be overwritten with the intersection.
+ *
+ * RETURNS:
+ * %true if rectangle @r1 is still visible after the operation,
+ * %false otherwise.
+ */
+bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
+{
+	r1->x1 = max(r1->x1, r2->x1);
+	r1->y1 = max(r1->y1, r2->y1);
+	r1->x2 = min(r1->x2, r2->x2);
+	r1->y2 = min(r1->y2, r2->y2);
+
+	return drm_rect_visible(r1);
+}
+EXPORT_SYMBOL(drm_rect_intersect);
+
+/**
+ * drm_rect_clip_scaled - perform a scaled clip operation
+ * @src: source window rectangle
+ * @dst: destination window rectangle
+ * @clip: clip rectangle
+ * @hscale: horizontal scaling factor
+ * @vscale: vertical scaling factor
+ *
+ * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
+ * same amounts multiplied by @hscale and @vscale.
+ *
+ * RETURNS:
+ * %true if rectangle @dst is still visible after being clipped,
+ * %false otherwise
+ */
+bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
+			  const struct drm_rect *clip,
+			  int hscale, int vscale)
+{
+	int diff;
+
+	diff = clip->x1 - dst->x1;
+	if (diff > 0) {
+		int64_t tmp = src->x1 + (int64_t) diff * hscale;
+		src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
+	}
+	diff = clip->y1 - dst->y1;
+	if (diff > 0) {
+		int64_t tmp = src->y1 + (int64_t) diff * vscale;
+		src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
+	}
+	diff = dst->x2 - clip->x2;
+	if (diff > 0) {
+		int64_t tmp = src->x2 - (int64_t) diff * hscale;
+		src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
+	}
+	diff = dst->y2 - clip->y2;
+	if (diff > 0) {
+		int64_t tmp = src->y2 - (int64_t) diff * vscale;
+		src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
+	}
+
+	return drm_rect_intersect(dst, clip);
+}
+EXPORT_SYMBOL(drm_rect_clip_scaled);
+
+static int drm_calc_scale(int src, int dst)
+{
+	int scale = 0;
+
+	if (src < 0 || dst < 0)
+		return -EINVAL;
+
+	if (dst == 0)
+		return 0;
+
+	scale = src / dst;
+
+	return scale;
+}
+
+/**
+ * drm_rect_calc_hscale - calculate the horizontal scaling factor
+ * @src: source window rectangle
+ * @dst: destination window rectangle
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * RETURNS:
+ * The horizontal scaling factor, or errno of out of limits.
+ */
+int drm_rect_calc_hscale(const struct drm_rect *src,
+			 const struct drm_rect *dst,
+			 int min_hscale, int max_hscale)
+{
+	int src_w = drm_rect_width(src);
+	int dst_w = drm_rect_width(dst);
+	int hscale = drm_calc_scale(src_w, dst_w);
+
+	if (hscale < 0 || dst_w == 0)
+		return hscale;
+
+	if (hscale < min_hscale || hscale > max_hscale)
+		return -ERANGE;
+
+	return hscale;
+}
+EXPORT_SYMBOL(drm_rect_calc_hscale);
+
+/**
+ * drm_rect_calc_vscale - calculate the vertical scaling factor
+ * @src: source window rectangle
+ * @dst: destination window rectangle
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * RETURNS:
+ * The vertical scaling factor, or errno of out of limits.
+ */
+int drm_rect_calc_vscale(const struct drm_rect *src,
+			 const struct drm_rect *dst,
+			 int min_vscale, int max_vscale)
+{
+	int src_h = drm_rect_height(src);
+	int dst_h = drm_rect_height(dst);
+	int vscale = drm_calc_scale(src_h, dst_h);
+
+	if (vscale < 0 || dst_h == 0)
+		return vscale;
+
+	if (vscale < min_vscale || vscale > max_vscale)
+		return -ERANGE;
+
+	return vscale;
+}
+EXPORT_SYMBOL(drm_rect_calc_vscale);
+
+/**
+ * drm_calc_hscale_relaxed - calculate the horizontal scaling factor
+ * @src: source window rectangle
+ * @dst: destination window rectangle
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of rectangle @dst to compensate.
+ *
+ * If the calculated scaling factor is above @max_vscale,
+ * decrease the height of rectangle @src to compensate.
+ *
+ * RETURNS:
+ * The horizontal scaling factor.
+ */
+int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
+				 struct drm_rect *dst,
+				 int min_hscale, int max_hscale)
+{
+	int src_w = drm_rect_width(src);
+	int dst_w = drm_rect_width(dst);
+	int hscale = drm_calc_scale(src_w, dst_w);
+
+	if (hscale < 0 || dst_w == 0)
+		return hscale;
+
+	if (hscale < min_hscale) {
+		int max_dst_w = src_w / min_hscale;
+
+		drm_rect_adjust_size(dst, max_dst_w - dst_w, 0);
+
+		return min_hscale;
+	}
+
+	if (hscale > max_hscale) {
+		int max_src_w = dst_w * max_hscale;
+
+		drm_rect_adjust_size(src, max_src_w - src_w, 0);
+
+		return max_hscale;
+	}
+
+	return hscale;
+}
+EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed);
+
+/**
+ * drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor
+ * @src: source window rectangle
+ * @dst: destination window rectangle
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of rectangle @dst to compensate.
+ *
+ * If the calculated scaling factor is above @max_vscale,
+ * decrease the height of rectangle @src to compensate.
+ *
+ * RETURNS:
+ * The vertical scaling factor.
+ */
+int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
+				 struct drm_rect *dst,
+				 int min_vscale, int max_vscale)
+{
+	int src_h = drm_rect_height(src);
+	int dst_h = drm_rect_height(dst);
+	int vscale = drm_calc_scale(src_h, dst_h);
+
+	if (vscale < 0 || dst_h == 0)
+		return vscale;
+
+	if (vscale < min_vscale) {
+		int max_dst_h = src_h / min_vscale;
+
+		drm_rect_adjust_size(dst, 0, max_dst_h - dst_h);
+
+		return min_vscale;
+	}
+
+	if (vscale > max_vscale) {
+		int max_src_h = dst_h * max_vscale;
+
+		drm_rect_adjust_size(src, 0, max_src_h - src_h);
+
+		return max_vscale;
+	}
+
+	return vscale;
+}
+EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
+
+/**
+ * drm_rect_debug_print - print the rectangle information
+ * @r: rectangle to print
+ * @fixed_point: rectangle is in 16.16 fixed point format
+ */
+void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point)
+{
+	int w = drm_rect_width(r);
+	int h = drm_rect_height(r);
+
+	if (fixed_point)
+		DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n",
+			      w >> 16, ((w & 0xffff) * 15625) >> 10,
+			      h >> 16, ((h & 0xffff) * 15625) >> 10,
+			      r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
+			      r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
+	else
+		DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
+}
+EXPORT_SYMBOL(drm_rect_debug_print);

+ 4 - 10
drivers/gpu/drm/drm_stub.c

@@ -203,7 +203,7 @@ EXPORT_SYMBOL(drm_master_put);
 int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	int ret;
+	int ret = 0;
 
 	if (file_priv->is_master)
 		return 0;
@@ -229,7 +229,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 	}
 	mutex_unlock(&dev->struct_mutex);
 
-	return 0;
+	return ret;
 }
 
 int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
@@ -451,14 +451,8 @@ void drm_put_dev(struct drm_device *dev)
 
 	drm_lastclose(dev);
 
-	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
-	    dev->agp && dev->agp->agp_mtrr >= 0) {
-		int retval;
-		retval = mtrr_del(dev->agp->agp_mtrr,
-				  dev->agp->agp_info.aper_base,
-				  dev->agp->agp_info.aper_size * 1024 * 1024);
-		DRM_DEBUG("mtrr_del=%d\n", retval);
-	}
+	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp)
+		arch_phys_wc_del(dev->agp->agp_mtrr);
 
 	if (dev->driver->unload)
 		dev->driver->unload(dev);

+ 29 - 4
drivers/gpu/drm/drm_sysfs.c

@@ -30,14 +30,14 @@ static struct device_type drm_sysfs_device_minor = {
 };
 
 /**
- * drm_class_suspend - DRM class suspend hook
+ * __drm_class_suspend - internal DRM class suspend routine
  * @dev: Linux device to suspend
  * @state: power state to enter
  *
  * Just figures out what the actual struct drm_device associated with
  * @dev is and calls its suspend hook, if present.
  */
-static int drm_class_suspend(struct device *dev, pm_message_t state)
+static int __drm_class_suspend(struct device *dev, pm_message_t state)
 {
 	if (dev->type == &drm_sysfs_device_minor) {
 		struct drm_minor *drm_minor = to_drm_minor(dev);
@@ -51,6 +51,26 @@ static int drm_class_suspend(struct device *dev, pm_message_t state)
 	return 0;
 }
 
+/**
+ * drm_class_suspend - internal DRM class suspend hook. Simply calls
+ * __drm_class_suspend() with the correct pm state.
+ * @dev: Linux device to suspend
+ */
+static int drm_class_suspend(struct device *dev)
+{
+	return __drm_class_suspend(dev, PMSG_SUSPEND);
+}
+
+/**
+ * drm_class_freeze - internal DRM class freeze hook. Simply calls
+ * __drm_class_suspend() with the correct pm state.
+ * @dev: Linux device to freeze
+ */
+static int drm_class_freeze(struct device *dev)
+{
+	return __drm_class_suspend(dev, PMSG_FREEZE);
+}
+
 /**
  * drm_class_resume - DRM class resume hook
  * @dev: Linux device to resume
@@ -72,6 +92,12 @@ static int drm_class_resume(struct device *dev)
 	return 0;
 }
 
+static const struct dev_pm_ops drm_class_dev_pm_ops = {
+	.suspend	= drm_class_suspend,
+	.resume		= drm_class_resume,
+	.freeze		= drm_class_freeze,
+};
+
 static char *drm_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
@@ -106,8 +132,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
 		goto err_out;
 	}
 
-	class->suspend = drm_class_suspend;
-	class->resume = drm_class_resume;
+	class->pm = &drm_class_dev_pm_ops;
 
 	err = class_create_file(class, &class_attr_version.attr);
 	if (err)

+ 3 - 3
drivers/gpu/drm/drm_trace.h

@@ -21,7 +21,7 @@ TRACE_EVENT(drm_vblank_event,
 		    __entry->crtc = crtc;
 		    __entry->seq = seq;
 		    ),
-	    TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq)
+	    TP_printk("crtc=%d, seq=%u", __entry->crtc, __entry->seq)
 );
 
 TRACE_EVENT(drm_vblank_event_queued,
@@ -37,7 +37,7 @@ TRACE_EVENT(drm_vblank_event_queued,
 		    __entry->crtc = crtc;
 		    __entry->seq = seq;
 		    ),
-	    TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
+	    TP_printk("pid=%d, crtc=%d, seq=%u", __entry->pid, __entry->crtc, \
 		      __entry->seq)
 );
 
@@ -54,7 +54,7 @@ TRACE_EVENT(drm_vblank_event_delivered,
 		    __entry->crtc = crtc;
 		    __entry->seq = seq;
 		    ),
-	    TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
+	    TP_printk("pid=%d, crtc=%d, seq=%u", __entry->pid, __entry->crtc, \
 		      __entry->seq)
 );
 

+ 10 - 14
drivers/gpu/drm/drm_vm.c

@@ -43,18 +43,19 @@
 static void drm_vm_open(struct vm_area_struct *vma);
 static void drm_vm_close(struct vm_area_struct *vma);
 
-static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
+static pgprot_t drm_io_prot(struct drm_local_map *map,
+			    struct vm_area_struct *vma)
 {
 	pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
 
 #if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
-		pgprot_val(tmp) |= _PAGE_PCD;
-		pgprot_val(tmp) &= ~_PAGE_PWT;
-	}
+	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
+		tmp = pgprot_noncached(tmp);
+	else
+		tmp = pgprot_writecombine(tmp);
 #elif defined(__powerpc__)
 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
-	if (map_type == _DRM_REGISTERS)
+	if (map->type == _DRM_REGISTERS)
 		pgprot_val(tmp) |= _PAGE_GUARDED;
 #elif defined(__ia64__)
 	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
@@ -250,13 +251,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-				if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
+				if (drm_core_has_MTRR(dev))
+					arch_phys_wc_del(map->mtrr);
 				iounmap(map->handle);
 				break;
 			case _DRM_SHM:
@@ -617,7 +613,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
 		offset = drm_core_get_reg_ofs(dev);
-		vma->vm_page_prot = drm_io_prot(map->type, vma);
+		vma->vm_page_prot = drm_io_prot(map, vma);
 		if (io_remap_pfn_range(vma, vma->vm_start,
 				       (map->offset + offset) >> PAGE_SHIFT,
 				       vma->vm_end - vma->vm_start,

+ 2 - 0
drivers/gpu/drm/exynos/exynos_ddc.c

@@ -52,6 +52,8 @@ static struct i2c_device_id ddc_idtable[] = {
 static struct of_device_id hdmiddc_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-hdmiddc",
+	}, {
+		.compatible = "samsung,exynos4210-hdmiddc",
 	}, {
 		/* end node */
 	}

+ 6 - 14
drivers/gpu/drm/exynos/exynos_drm_buf.c

@@ -24,8 +24,6 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
 	enum dma_attr attr;
 	unsigned int nr_pages;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (buf->dma_addr) {
 		DRM_DEBUG_KMS("already allocated.\n");
 		return 0;
@@ -59,8 +57,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
 		dma_addr_t start_addr;
 		unsigned int i = 0;
 
-		buf->pages = kzalloc(sizeof(struct page) * nr_pages,
-					GFP_KERNEL);
+		buf->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
 		if (!buf->pages) {
 			DRM_ERROR("failed to allocate pages.\n");
 			return -ENOMEM;
@@ -71,8 +68,8 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
 					&buf->dma_attrs);
 		if (!buf->kvaddr) {
 			DRM_ERROR("failed to allocate buffer.\n");
-			kfree(buf->pages);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_free;
 		}
 
 		start_addr = buf->dma_addr;
@@ -109,9 +106,9 @@ err_free_attrs:
 	dma_free_attrs(dev->dev, buf->size, buf->pages,
 			(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
 	buf->dma_addr = (dma_addr_t)NULL;
-
+err_free:
 	if (!is_drm_iommu_supported(dev))
-		kfree(buf->pages);
+		drm_free_large(buf->pages);
 
 	return ret;
 }
@@ -119,8 +116,6 @@ err_free_attrs:
 static void lowlevel_buffer_deallocate(struct drm_device *dev,
 		unsigned int flags, struct exynos_drm_gem_buf *buf)
 {
-	DRM_DEBUG_KMS("%s.\n", __FILE__);
-
 	if (!buf->dma_addr) {
 		DRM_DEBUG_KMS("dma_addr is invalid.\n");
 		return;
@@ -138,7 +133,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
 	if (!is_drm_iommu_supported(dev)) {
 		dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
 				(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
-		kfree(buf->pages);
+		drm_free_large(buf->pages);
 	} else
 		dma_free_attrs(dev->dev, buf->size, buf->pages,
 				(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
@@ -151,7 +146,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
 {
 	struct exynos_drm_gem_buf *buffer;
 
-	DRM_DEBUG_KMS("%s.\n", __FILE__);
 	DRM_DEBUG_KMS("desired size = 0x%x\n", size);
 
 	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
@@ -167,8 +161,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
 void exynos_drm_fini_buf(struct drm_device *dev,
 				struct exynos_drm_gem_buf *buffer)
 {
-	DRM_DEBUG_KMS("%s.\n", __FILE__);
-
 	if (!buffer) {
 		DRM_DEBUG_KMS("buffer is null.\n");
 		return;

+ 2 - 49
drivers/gpu/drm/exynos/exynos_drm_connector.c

@@ -34,7 +34,6 @@ convert_to_display_mode(struct drm_display_mode *mode,
 			struct exynos_drm_panel_info *panel)
 {
 	struct fb_videomode *timing = &panel->timing;
-	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	mode->clock = timing->pixclock / 1000;
 	mode->vrefresh = timing->refresh;
@@ -58,37 +57,6 @@ convert_to_display_mode(struct drm_display_mode *mode,
 		mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 }
 
-/* convert drm_display_mode to exynos_video_timings */
-static inline void
-convert_to_video_timing(struct fb_videomode *timing,
-			struct drm_display_mode *mode)
-{
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	memset(timing, 0, sizeof(*timing));
-
-	timing->pixclock = mode->clock * 1000;
-	timing->refresh = drm_mode_vrefresh(mode);
-
-	timing->xres = mode->hdisplay;
-	timing->right_margin = mode->hsync_start - mode->hdisplay;
-	timing->hsync_len = mode->hsync_end - mode->hsync_start;
-	timing->left_margin = mode->htotal - mode->hsync_end;
-
-	timing->yres = mode->vdisplay;
-	timing->lower_margin = mode->vsync_start - mode->vdisplay;
-	timing->vsync_len = mode->vsync_end - mode->vsync_start;
-	timing->upper_margin = mode->vtotal - mode->vsync_end;
-
-	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-		timing->vmode = FB_VMODE_INTERLACED;
-	else
-		timing->vmode = FB_VMODE_NONINTERLACED;
-
-	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
-		timing->vmode |= FB_VMODE_DOUBLE;
-}
-
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 {
 	struct exynos_drm_connector *exynos_connector =
@@ -99,8 +67,6 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 	unsigned int count = 0;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!display_ops) {
 		DRM_DEBUG_KMS("display_ops is null.\n");
 		return 0;
@@ -168,15 +134,12 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 					to_exynos_connector(connector);
 	struct exynos_drm_manager *manager = exynos_connector->manager;
 	struct exynos_drm_display_ops *display_ops = manager->display_ops;
-	struct fb_videomode timing;
 	int ret = MODE_BAD;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	convert_to_video_timing(&timing, mode);
-
-	if (display_ops && display_ops->check_timing)
-		if (!display_ops->check_timing(manager->dev, (void *)&timing))
+	if (display_ops && display_ops->check_mode)
+		if (!display_ops->check_mode(manager->dev, mode))
 			ret = MODE_OK;
 
 	return ret;
@@ -190,8 +153,6 @@ struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
 	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
 				   DRM_MODE_OBJECT_ENCODER);
 	if (!obj) {
@@ -234,8 +195,6 @@ void exynos_drm_display_power(struct drm_connector *connector, int mode)
 static void exynos_drm_connector_dpms(struct drm_connector *connector,
 					int mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * in case that drm_crtc_helper_set_mode() is called,
 	 * encoder/crtc->funcs->dpms() will be just returned
@@ -282,8 +241,6 @@ exynos_drm_connector_detect(struct drm_connector *connector, bool force)
 					manager->display_ops;
 	enum drm_connector_status status = connector_status_disconnected;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (display_ops && display_ops->is_connected) {
 		if (display_ops->is_connected(manager->dev))
 			status = connector_status_connected;
@@ -299,8 +256,6 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
 	struct exynos_drm_connector *exynos_connector =
 		to_exynos_connector(connector);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 	kfree(exynos_connector);
@@ -322,8 +277,6 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 	int type;
 	int err;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
 	if (!exynos_connector) {
 		DRM_ERROR("failed to allocate connector\n");

+ 0 - 12
drivers/gpu/drm/exynos/exynos_drm_core.c

@@ -27,8 +27,6 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 	struct drm_connector *connector;
 	int ret;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	subdrv->manager->dev = subdrv->dev;
 
 	/* create and initialize a encoder for this sub driver. */
@@ -102,8 +100,6 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
 static void exynos_drm_subdrv_remove(struct drm_device *dev,
 				      struct exynos_drm_subdrv *subdrv)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (subdrv->remove)
 		subdrv->remove(dev, subdrv->dev);
 }
@@ -114,8 +110,6 @@ int exynos_drm_device_register(struct drm_device *dev)
 	unsigned int fine_cnt = 0;
 	int err;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (!dev)
 		return -EINVAL;
 
@@ -158,8 +152,6 @@ int exynos_drm_device_unregister(struct drm_device *dev)
 {
 	struct exynos_drm_subdrv *subdrv;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (!dev) {
 		WARN(1, "Unexpected drm device unregister!\n");
 		return -EINVAL;
@@ -176,8 +168,6 @@ EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
 
 int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (!subdrv)
 		return -EINVAL;
 
@@ -189,8 +179,6 @@ EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
 
 int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (!subdrv)
 		return -EINVAL;
 

+ 5 - 34
drivers/gpu/drm/exynos/exynos_drm_crtc.c

@@ -76,8 +76,6 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* drm framework doesn't check NULL. */
 }
 
@@ -85,8 +83,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 	exynos_plane_commit(exynos_crtc->plane);
 	exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
@@ -97,8 +93,6 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 			    const struct drm_display_mode *mode,
 			    struct drm_display_mode *adjusted_mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* drm framework doesn't check NULL */
 	return true;
 }
@@ -115,8 +109,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	int pipe = exynos_crtc->pipe;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * copy the mode data adjusted by mode_fixup() into crtc->mode
 	 * so that hardware can be seet to proper mode.
@@ -139,7 +131,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	return 0;
 }
 
-static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
 					  struct drm_framebuffer *old_fb)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
@@ -148,8 +140,6 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	unsigned int crtc_h;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* when framebuffer changing is requested, crtc's dpms should be on */
 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
 		DRM_ERROR("failed framebuffer changing request.\n");
@@ -169,18 +159,16 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	return 0;
 }
 
-static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
+static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+					  struct drm_framebuffer *old_fb)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-	/* drm framework doesn't check NULL */
+	return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb);
 }
 
 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
@@ -192,7 +180,6 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
 	.mode_fixup	= exynos_drm_crtc_mode_fixup,
 	.mode_set	= exynos_drm_crtc_mode_set,
 	.mode_set_base	= exynos_drm_crtc_mode_set_base,
-	.load_lut	= exynos_drm_crtc_load_lut,
 	.disable	= exynos_drm_crtc_disable,
 };
 
@@ -206,8 +193,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 	struct drm_framebuffer *old_fb = crtc->fb;
 	int ret = -EINVAL;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* when the page flip is requested, crtc's dpms should be on */
 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
 		DRM_ERROR("failed page flip request.\n");
@@ -237,7 +222,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
 		spin_unlock_irq(&dev->event_lock);
 
 		crtc->fb = fb;
-		ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y,
+		ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
 						    NULL);
 		if (ret) {
 			crtc->fb = old_fb;
@@ -260,8 +245,6 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 	struct exynos_drm_private *private = crtc->dev->dev_private;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	private->crtc[exynos_crtc->pipe] = NULL;
 
 	drm_crtc_cleanup(crtc);
@@ -276,8 +259,6 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
 	struct exynos_drm_private *dev_priv = dev->dev_private;
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (property == dev_priv->crtc_mode_property) {
 		enum exynos_crtc_mode mode = val;
 
@@ -322,8 +303,6 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
 	struct exynos_drm_private *dev_priv = dev->dev_private;
 	struct drm_property *prop;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	prop = dev_priv->crtc_mode_property;
 	if (!prop) {
 		prop = drm_property_create_enum(dev, 0, "mode", mode_names,
@@ -343,8 +322,6 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 	struct exynos_drm_private *private = dev->dev_private;
 	struct drm_crtc *crtc;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
 	if (!exynos_crtc) {
 		DRM_ERROR("failed to allocate exynos crtc\n");
@@ -379,8 +356,6 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
 	struct exynos_drm_crtc *exynos_crtc =
 		to_exynos_crtc(private->crtc[crtc]);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
 		return -EPERM;
 
@@ -396,8 +371,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
 	struct exynos_drm_crtc *exynos_crtc =
 		to_exynos_crtc(private->crtc[crtc]);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
 		return;
 
@@ -413,8 +386,6 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
 	unsigned long flags;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	spin_lock_irqsave(&dev->event_lock, flags);
 
 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,

+ 0 - 6
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c

@@ -71,8 +71,6 @@ static struct sg_table *
 	unsigned int i;
 	int nents, ret;
 
-	DRM_DEBUG_PRIME("%s\n", __FILE__);
-
 	/* just return current sgt if already requested. */
 	if (exynos_attach->dir == dir && exynos_attach->is_mapped)
 		return &exynos_attach->sgt;
@@ -133,8 +131,6 @@ static void exynos_dmabuf_release(struct dma_buf *dmabuf)
 {
 	struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;
 
-	DRM_DEBUG_PRIME("%s\n", __FILE__);
-
 	/*
 	 * exynos_dmabuf_release() call means that file object's
 	 * f_count is 0 and it calls drm_gem_object_handle_unreference()
@@ -219,8 +215,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
 	struct exynos_drm_gem_buf *buffer;
 	int ret;
 
-	DRM_DEBUG_PRIME("%s\n", __FILE__);
-
 	/* is this one of own objects? */
 	if (dma_buf->ops == &exynos_dmabuf_ops) {
 		struct drm_gem_object *obj;

+ 8 - 21
drivers/gpu/drm/exynos/exynos_drm_drv.c

@@ -46,8 +46,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 	int ret;
 	int nr;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
 	if (!private) {
 		DRM_ERROR("failed to allocate private\n");
@@ -140,8 +138,6 @@ err_crtc:
 
 static int exynos_drm_unload(struct drm_device *dev)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	exynos_drm_fbdev_fini(dev);
 	exynos_drm_device_unregister(dev);
 	drm_vblank_cleanup(dev);
@@ -159,8 +155,7 @@ static int exynos_drm_unload(struct drm_device *dev)
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv;
-
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+	int ret;
 
 	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
 	if (!file_priv)
@@ -168,7 +163,13 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 
 	file->driver_priv = file_priv;
 
-	return exynos_drm_subdrv_open(dev, file);
+	ret = exynos_drm_subdrv_open(dev, file);
+	if (ret) {
+		kfree(file_priv);
+		file->driver_priv = NULL;
+	}
+
+	return ret;
 }
 
 static void exynos_drm_preclose(struct drm_device *dev,
@@ -178,8 +179,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
 	struct drm_pending_vblank_event *e, *t;
 	unsigned long flags;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	/* release events of current file */
 	spin_lock_irqsave(&dev->event_lock, flags);
 	list_for_each_entry_safe(e, t, &private->pageflip_event_list,
@@ -196,8 +195,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
 
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	if (!file->driver_priv)
 		return;
 
@@ -207,8 +204,6 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 
 static void exynos_drm_lastclose(struct drm_device *dev)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	exynos_drm_fbdev_restore_mode(dev);
 }
 
@@ -292,8 +287,6 @@ static struct drm_driver exynos_drm_driver = {
 
 static int exynos_drm_platform_probe(struct platform_device *pdev)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 	exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
 
@@ -302,8 +295,6 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
 
 static int exynos_drm_platform_remove(struct platform_device *pdev)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	drm_platform_exit(&exynos_drm_driver, pdev);
 
 	return 0;
@@ -322,8 +313,6 @@ static int __init exynos_drm_init(void)
 {
 	int ret;
 
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 #ifdef CONFIG_DRM_EXYNOS_FIMD
 	ret = platform_driver_register(&fimd_driver);
 	if (ret < 0)
@@ -455,8 +444,6 @@ out_fimd:
 
 static void __exit exynos_drm_exit(void)
 {
-	DRM_DEBUG_DRIVER("%s\n", __FILE__);
-
 	platform_device_unregister(exynos_drm_pdev);
 
 	platform_driver_unregister(&exynos_drm_platform_driver);

+ 2 - 2
drivers/gpu/drm/exynos/exynos_drm_drv.h

@@ -142,7 +142,7 @@ struct exynos_drm_overlay {
  * @is_connected: check for that display is connected or not.
  * @get_edid: get edid modes from display driver.
  * @get_panel: get panel object from display driver.
- * @check_timing: check if timing is valid or not.
+ * @check_mode: check if mode is valid or not.
  * @power_on: display device on or off.
  */
 struct exynos_drm_display_ops {
@@ -151,7 +151,7 @@ struct exynos_drm_display_ops {
 	struct edid *(*get_edid)(struct device *dev,
 			struct drm_connector *connector);
 	void *(*get_panel)(struct device *dev);
-	int (*check_timing)(struct device *dev, void *timing);
+	int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
 	int (*power_on)(struct device *dev, int mode);
 };
 

+ 1 - 27
drivers/gpu/drm/exynos/exynos_drm_encoder.c

@@ -61,7 +61,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
 
-	DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
+	DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
 
 	if (exynos_encoder->dpms == mode) {
 		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
@@ -104,8 +104,6 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
 	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder)
 			if (manager_ops && manager_ops->mode_fixup)
@@ -155,8 +153,6 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 	struct exynos_drm_manager *manager;
 	struct exynos_drm_manager_ops *manager_ops;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder) {
 			struct exynos_drm_encoder *exynos_encoder;
@@ -189,8 +185,6 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 
 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* drm framework doesn't check NULL. */
 }
 
@@ -200,8 +194,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 	struct exynos_drm_manager *manager = exynos_encoder->manager;
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (manager_ops && manager_ops->commit)
 		manager_ops->commit(manager->dev);
 
@@ -274,8 +266,6 @@ static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
 	struct exynos_drm_encoder *exynos_encoder =
 		to_exynos_encoder(encoder);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_encoder->manager->pipe = -1;
 
 	drm_encoder_cleanup(encoder);
@@ -315,8 +305,6 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
 {
 	struct drm_encoder *encoder;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
 		encoder->possible_clones = exynos_drm_encoder_clones(encoder);
 }
@@ -329,8 +317,6 @@ exynos_drm_encoder_create(struct drm_device *dev,
 	struct drm_encoder *encoder;
 	struct exynos_drm_encoder *exynos_encoder;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!manager || !possible_crtcs)
 		return NULL;
 
@@ -427,8 +413,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	int mode = *(int *)data;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (manager_ops && manager_ops->dpms)
 		manager_ops->dpms(manager->dev, mode);
 
@@ -449,8 +433,6 @@ void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
 		to_exynos_encoder(encoder)->manager;
 	int pipe = *(int *)data;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * when crtc is detached from encoder, this pipe is used
 	 * to select manager operation
@@ -465,8 +447,6 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 	struct exynos_drm_overlay *overlay = data;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (overlay_ops && overlay_ops->mode_set)
 		overlay_ops->mode_set(manager->dev, overlay);
 }
@@ -478,8 +458,6 @@ void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 	int zpos = DEFAULT_ZPOS;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (data)
 		zpos = *(int *)data;
 
@@ -494,8 +472,6 @@ void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 	int zpos = DEFAULT_ZPOS;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (data)
 		zpos = *(int *)data;
 
@@ -510,8 +486,6 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 	int zpos = DEFAULT_ZPOS;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (data)
 		zpos = *(int *)data;
 

+ 0 - 10
drivers/gpu/drm/exynos/exynos_drm_fb.c

@@ -70,8 +70,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
 	unsigned int i;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* make sure that overlay data are updated before relesing fb. */
 	exynos_drm_encoder_complete_scanout(fb);
 
@@ -97,8 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
 {
 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* This fb should have only one gem object. */
 	if (WARN_ON(exynos_fb->buf_cnt != 1))
 		return -EINVAL;
@@ -112,8 +108,6 @@ static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
 				unsigned color, struct drm_clip_rect *clips,
 				unsigned num_clips)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO */
 
 	return 0;
@@ -225,8 +219,6 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
 	struct exynos_drm_fb *exynos_fb;
 	int i, ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
 	if (!exynos_fb) {
 		DRM_ERROR("failed to allocate exynos drm framebuffer\n");
@@ -293,8 +285,6 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
 	struct exynos_drm_gem_buf *buffer;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (index >= MAX_FB_BUFFER)
 		return NULL;
 

+ 0 - 8
drivers/gpu/drm/exynos/exynos_drm_fbdev.c

@@ -43,8 +43,6 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
 	unsigned long vm_size;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 
 	vm_size = vma->vm_end - vma->vm_start;
@@ -84,8 +82,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 	unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
 	unsigned long offset;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
 	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
 
@@ -148,8 +144,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 	unsigned long size;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
 			sizes->surface_width, sizes->surface_height,
 			sizes->surface_bpp);
@@ -238,8 +232,6 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
 	unsigned int num_crtc;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
 		return 0;
 

+ 53 - 76
drivers/gpu/drm/exynos/exynos_drm_fimc.c

@@ -175,8 +175,6 @@ static void fimc_sw_reset(struct fimc_context *ctx)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* stop dma operation */
 	cfg = fimc_read(EXYNOS_CISTATUS);
 	if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
@@ -210,8 +208,6 @@ static void fimc_sw_reset(struct fimc_context *ctx)
 
 static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
 				  SYSREG_FIMD0WB_DEST_MASK,
 				  ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
@@ -221,7 +217,7 @@ static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
+	DRM_DEBUG_KMS("wb[%d]\n", wb);
 
 	cfg = fimc_read(EXYNOS_CIGCTRL);
 	cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
@@ -257,10 +253,10 @@ static void fimc_set_polarity(struct fimc_context *ctx,
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
-		__func__, pol->inv_pclk, pol->inv_vsync);
-	DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
-		__func__, pol->inv_href, pol->inv_hsync);
+	DRM_DEBUG_KMS("inv_pclk[%d]inv_vsync[%d]\n",
+		pol->inv_pclk, pol->inv_vsync);
+	DRM_DEBUG_KMS("inv_href[%d]inv_hsync[%d]\n",
+		pol->inv_href, pol->inv_hsync);
 
 	cfg = fimc_read(EXYNOS_CIGCTRL);
 	cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
@@ -282,7 +278,7 @@ static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	cfg = fimc_read(EXYNOS_CIGCTRL);
 	if (enable)
@@ -298,7 +294,7 @@ static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
+	DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
 			enable, overflow, level);
 
 	cfg = fimc_read(EXYNOS_CIGCTRL);
@@ -319,8 +315,6 @@ static void fimc_clear_irq(struct fimc_context *ctx)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	cfg = fimc_read(EXYNOS_CIGCTRL);
 	cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
 	fimc_write(cfg, EXYNOS_CIGCTRL);
@@ -335,7 +329,7 @@ static bool fimc_check_ovf(struct fimc_context *ctx)
 	flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
 		EXYNOS_CISTATUS_OVFICR;
 
-	DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
+	DRM_DEBUG_KMS("flag[0x%x]\n", flag);
 
 	if (status & flag) {
 		cfg = fimc_read(EXYNOS_CIWDOFST);
@@ -364,7 +358,7 @@ static bool fimc_check_frame_end(struct fimc_context *ctx)
 
 	cfg = fimc_read(EXYNOS_CISTATUS);
 
-	DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
+	DRM_DEBUG_KMS("cfg[0x%x]\n", cfg);
 
 	if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
 		return false;
@@ -380,15 +374,13 @@ static int fimc_get_buf_id(struct fimc_context *ctx)
 	u32 cfg;
 	int frame_cnt, buf_id;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	cfg = fimc_read(EXYNOS_CISTATUS2);
 	frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
 
 	if (frame_cnt == 0)
 		frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
 
-	DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__,
+	DRM_DEBUG_KMS("present[%d]before[%d]\n",
 		EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
 		EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
 
@@ -398,7 +390,7 @@ static int fimc_get_buf_id(struct fimc_context *ctx)
 	}
 
 	buf_id = frame_cnt - 1;
-	DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+	DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
 
 	return buf_id;
 }
@@ -407,7 +399,7 @@ static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	cfg = fimc_read(EXYNOS_CIOCTRL);
 	if (enable)
@@ -424,7 +416,7 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	/* RGB */
 	cfg = fimc_read(EXYNOS_CISCCTRL);
@@ -497,7 +489,7 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	cfg = fimc_read(EXYNOS_MSCTRL);
 	cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
@@ -557,8 +549,7 @@ static int fimc_src_set_transf(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg1, cfg2;
 
-	DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
-		degree, flip);
+	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
 
 	cfg1 = fimc_read(EXYNOS_MSCTRL);
 	cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
@@ -621,10 +612,9 @@ static int fimc_set_window(struct fimc_context *ctx,
 	v1 = pos->y;
 	v2 = sz->vsize - pos->h - pos->y;
 
-	DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
-	__func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
-	DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
-		h1, h2, v1, v2);
+	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
+		pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
+	DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
 
 	/*
 	 * set window offset 1, 2 size
@@ -653,8 +643,8 @@ static int fimc_src_set_size(struct device *dev, int swap,
 	struct drm_exynos_sz img_sz = *sz;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
-		__func__, swap, sz->hsize, sz->vsize);
+	DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
+		swap, sz->hsize, sz->vsize);
 
 	/* original size */
 	cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
@@ -662,8 +652,7 @@ static int fimc_src_set_size(struct device *dev, int swap,
 
 	fimc_write(cfg, EXYNOS_ORGISIZE);
 
-	DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
-		pos->x, pos->y, pos->w, pos->h);
+	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
 
 	if (swap) {
 		img_pos.w = pos->h;
@@ -720,7 +709,7 @@ static int fimc_src_set_addr(struct device *dev,
 
 	property = &c_node->property;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
+	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
 		property->prop_id, buf_id, buf_type);
 
 	if (buf_id > FIMC_MAX_SRC) {
@@ -772,7 +761,7 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	/* RGB */
 	cfg = fimc_read(EXYNOS_CISCCTRL);
@@ -851,7 +840,7 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	cfg = fimc_read(EXYNOS_CIEXTEN);
 
@@ -919,8 +908,7 @@ static int fimc_dst_set_transf(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
-		degree, flip);
+	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
 
 	cfg = fimc_read(EXYNOS_CITRGFMT);
 	cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
@@ -970,7 +958,7 @@ static int fimc_dst_set_transf(struct device *dev,
 
 static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
 {
-	DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
+	DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst);
 
 	if (src >= dst * 64) {
 		DRM_ERROR("failed to make ratio and shift.\n");
@@ -1039,20 +1027,20 @@ static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
 
 	pre_dst_width = src_w / pre_hratio;
 	pre_dst_height = src_h / pre_vratio;
-	DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
+	DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
 		pre_dst_width, pre_dst_height);
-	DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
-		__func__, pre_hratio, hfactor, pre_vratio, vfactor);
+	DRM_DEBUG_KMS("pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
+		pre_hratio, hfactor, pre_vratio, vfactor);
 
 	sc->hratio = (src_w << 14) / (dst_w << hfactor);
 	sc->vratio = (src_h << 14) / (dst_h << vfactor);
 	sc->up_h = (dst_w >= src_w) ? true : false;
 	sc->up_v = (dst_h >= src_h) ? true : false;
-	DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
-	__func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
+	DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
+		sc->hratio, sc->vratio, sc->up_h, sc->up_v);
 
 	shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
-	DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
+	DRM_DEBUG_KMS("shfactor[%d]\n", shfactor);
 
 	cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
 		EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
@@ -1070,10 +1058,10 @@ static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
 {
 	u32 cfg, cfg_ext;
 
-	DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
-		__func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
-	DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
-		__func__, sc->hratio, sc->vratio);
+	DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
+		sc->range, sc->bypass, sc->up_h, sc->up_v);
+	DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
+		sc->hratio, sc->vratio);
 
 	cfg = fimc_read(EXYNOS_CISCCTRL);
 	cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
@@ -1113,8 +1101,8 @@ static int fimc_dst_set_size(struct device *dev, int swap,
 	struct drm_exynos_sz img_sz = *sz;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
-		__func__, swap, sz->hsize, sz->vsize);
+	DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
+		swap, sz->hsize, sz->vsize);
 
 	/* original size */
 	cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
@@ -1122,8 +1110,7 @@ static int fimc_dst_set_size(struct device *dev, int swap,
 
 	fimc_write(cfg, EXYNOS_ORGOSIZE);
 
-	DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
-		__func__, pos->x, pos->y, pos->w, pos->h);
+	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
 
 	/* CSC ITU */
 	cfg = fimc_read(EXYNOS_CIGCTRL);
@@ -1180,7 +1167,7 @@ static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
 		if (cfg & (mask << i))
 			buf_num++;
 
-	DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
+	DRM_DEBUG_KMS("buf_num[%d]\n", buf_num);
 
 	return buf_num;
 }
@@ -1194,8 +1181,7 @@ static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
 	u32 mask = 0x00000001 << buf_id;
 	int ret = 0;
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
-		buf_id, buf_type);
+	DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
 
 	mutex_lock(&ctx->lock);
 
@@ -1252,7 +1238,7 @@ static int fimc_dst_set_addr(struct device *dev,
 
 	property = &c_node->property;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
+	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
 		property->prop_id, buf_id, buf_type);
 
 	if (buf_id > FIMC_MAX_DST) {
@@ -1302,7 +1288,7 @@ static struct exynos_drm_ipp_ops fimc_dst_ops = {
 
 static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
 {
-	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	if (enable) {
 		clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
@@ -1326,7 +1312,7 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
 		c_node->event_work;
 	int buf_id;
 
-	DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id);
 
 	fimc_clear_irq(ctx);
 	if (fimc_check_ovf(ctx))
@@ -1339,7 +1325,7 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
 	if (buf_id < 0)
 		return IRQ_HANDLED;
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
+	DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
 
 	if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
 		DRM_ERROR("failed to dequeue.\n");
@@ -1357,8 +1343,6 @@ static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
 {
 	struct drm_exynos_ipp_prop_list *prop_list;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
 	if (!prop_list) {
 		DRM_ERROR("failed to alloc property list.\n");
@@ -1402,7 +1386,7 @@ static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
 	case EXYNOS_DRM_FLIP_BOTH:
 		return true;
 	default:
-		DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+		DRM_DEBUG_KMS("invalid flip\n");
 		return false;
 	}
 }
@@ -1419,8 +1403,6 @@ static int fimc_ippdrv_check_property(struct device *dev,
 	bool swap;
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	for_each_ipp_ops(i) {
 		if ((i == EXYNOS_DRM_OPS_SRC) &&
 			(property->cmd == IPP_CMD_WB))
@@ -1526,8 +1508,6 @@ static void fimc_clear_addr(struct fimc_context *ctx)
 {
 	int i;
 
-	DRM_DEBUG_KMS("%s:\n", __func__);
-
 	for (i = 0; i < FIMC_MAX_SRC; i++) {
 		fimc_write(0, EXYNOS_CIIYSA(i));
 		fimc_write(0, EXYNOS_CIICBSA(i));
@@ -1545,8 +1525,6 @@ static int fimc_ippdrv_reset(struct device *dev)
 {
 	struct fimc_context *ctx = get_fimc_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* reset h/w block */
 	fimc_sw_reset(ctx);
 
@@ -1570,7 +1548,7 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	int ret, i;
 	u32 cfg0, cfg1;
 
-	DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -1679,7 +1657,7 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	struct drm_exynos_ipp_set_wb set_wb = {0, 0};
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
 
 	switch (cmd) {
 	case IPP_CMD_M2M:
@@ -1869,8 +1847,7 @@ static int fimc_probe(struct platform_device *pdev)
 		goto err_put_clk;
 	}
 
-	DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
-		(int)ippdrv);
+	DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
 
 	mutex_init(&ctx->lock);
 	platform_set_drvdata(pdev, ctx);
@@ -1917,7 +1894,7 @@ static int fimc_suspend(struct device *dev)
 {
 	struct fimc_context *ctx = get_fimc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	if (pm_runtime_suspended(dev))
 		return 0;
@@ -1929,7 +1906,7 @@ static int fimc_resume(struct device *dev)
 {
 	struct fimc_context *ctx = get_fimc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	if (!pm_runtime_suspended(dev))
 		return fimc_clk_ctrl(ctx, true);
@@ -1943,7 +1920,7 @@ static int fimc_runtime_suspend(struct device *dev)
 {
 	struct fimc_context *ctx = get_fimc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	return  fimc_clk_ctrl(ctx, false);
 }
@@ -1952,7 +1929,7 @@ static int fimc_runtime_resume(struct device *dev)
 {
 	struct fimc_context *ctx = get_fimc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	return  fimc_clk_ctrl(ctx, true);
 }

+ 74 - 72
drivers/gpu/drm/exynos/exynos_drm_fimd.c

@@ -63,14 +63,24 @@
 
 struct fimd_driver_data {
 	unsigned int timing_base;
+
+	unsigned int has_shadowcon:1;
+	unsigned int has_clksel:1;
+};
+
+static struct fimd_driver_data s3c64xx_fimd_driver_data = {
+	.timing_base = 0x0,
+	.has_clksel = 1,
 };
 
 static struct fimd_driver_data exynos4_fimd_driver_data = {
 	.timing_base = 0x0,
+	.has_shadowcon = 1,
 };
 
 static struct fimd_driver_data exynos5_fimd_driver_data = {
 	.timing_base = 0x20000,
+	.has_shadowcon = 1,
 };
 
 struct fimd_win_data {
@@ -107,10 +117,13 @@ struct fimd_context {
 	atomic_t			wait_vsync_event;
 
 	struct exynos_drm_panel_info *panel;
+	struct fimd_driver_data *driver_data;
 };
 
 #ifdef CONFIG_OF
 static const struct of_device_id fimd_driver_dt_match[] = {
+	{ .compatible = "samsung,s3c6400-fimd",
+	  .data = &s3c64xx_fimd_driver_data },
 	{ .compatible = "samsung,exynos4210-fimd",
 	  .data = &exynos4_fimd_driver_data },
 	{ .compatible = "samsung,exynos5250-fimd",
@@ -137,8 +150,6 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
 
 static bool fimd_display_is_connected(struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO. */
 
 	return true;
@@ -148,15 +159,11 @@ static void *fimd_get_panel(struct device *dev)
 {
 	struct fimd_context *ctx = get_fimd_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	return ctx->panel;
 }
 
-static int fimd_check_timing(struct device *dev, void *timing)
+static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO. */
 
 	return 0;
@@ -164,8 +171,6 @@ static int fimd_check_timing(struct device *dev, void *timing)
 
 static int fimd_display_power_on(struct device *dev, int mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO */
 
 	return 0;
@@ -175,7 +180,7 @@ static struct exynos_drm_display_ops fimd_display_ops = {
 	.type = EXYNOS_DISPLAY_TYPE_LCD,
 	.is_connected = fimd_display_is_connected,
 	.get_panel = fimd_get_panel,
-	.check_timing = fimd_check_timing,
+	.check_mode = fimd_check_mode,
 	.power_on = fimd_display_power_on,
 };
 
@@ -183,7 +188,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
 {
 	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
+	DRM_DEBUG_KMS("%d\n", mode);
 
 	mutex_lock(&ctx->lock);
 
@@ -221,8 +226,6 @@ static void fimd_apply(struct device *subdrv_dev)
 	struct fimd_win_data *win_data;
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
 		if (win_data->enabled && (ovl_ops && ovl_ops->commit))
@@ -239,15 +242,12 @@ static void fimd_commit(struct device *dev)
 	struct exynos_drm_panel_info *panel = ctx->panel;
 	struct fb_videomode *timing = &panel->timing;
 	struct fimd_driver_data *driver_data;
-	struct platform_device *pdev = to_platform_device(dev);
 	u32 val;
 
-	driver_data = drm_fimd_get_driver_data(pdev);
+	driver_data = ctx->driver_data;
 	if (ctx->suspended)
 		return;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* setup polarity values from machine code. */
 	writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
 
@@ -274,6 +274,11 @@ static void fimd_commit(struct device *dev)
 	val = ctx->vidcon0;
 	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
 
+	if (ctx->driver_data->has_clksel) {
+		val &= ~VIDCON0_CLKSEL_MASK;
+		val |= VIDCON0_CLKSEL_LCD;
+	}
+
 	if (ctx->clkdiv > 1)
 		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
 	else
@@ -292,8 +297,6 @@ static int fimd_enable_vblank(struct device *dev)
 	struct fimd_context *ctx = get_fimd_context(dev);
 	u32 val;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return -EPERM;
 
@@ -319,8 +322,6 @@ static void fimd_disable_vblank(struct device *dev)
 	struct fimd_context *ctx = get_fimd_context(dev);
 	u32 val;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return;
 
@@ -370,8 +371,6 @@ static void fimd_win_mode_set(struct device *dev,
 	int win;
 	unsigned long offset;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!overlay) {
 		dev_err(dev, "overlay is NULL\n");
 		return;
@@ -381,7 +380,7 @@ static void fimd_win_mode_set(struct device *dev,
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	offset = overlay->fb_x * (overlay->bpp >> 3);
@@ -418,8 +417,6 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
 	struct fimd_win_data *win_data = &ctx->win_data[win];
 	unsigned long val;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	val = WINCONx_ENWIN;
 
 	switch (win_data->bpp) {
@@ -478,8 +475,6 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win)
 	struct fimd_context *ctx = get_fimd_context(dev);
 	unsigned int keycon0 = 0, keycon1 = 0;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
 			WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
 
@@ -489,6 +484,33 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win)
 	writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
 }
 
+/**
+ * shadow_protect_win() - disable updating values from shadow registers at vsync
+ *
+ * @win: window to protect registers for
+ * @protect: 1 to protect (disable updates)
+ */
+static void fimd_shadow_protect_win(struct fimd_context *ctx,
+							int win, bool protect)
+{
+	u32 reg, bits, val;
+
+	if (ctx->driver_data->has_shadowcon) {
+		reg = SHADOWCON;
+		bits = SHADOWCON_WINx_PROTECT(win);
+	} else {
+		reg = PRTCON;
+		bits = PRTCON_PROTECT;
+	}
+
+	val = readl(ctx->regs + reg);
+	if (protect)
+		val |= bits;
+	else
+		val &= ~bits;
+	writel(val, ctx->regs + reg);
+}
+
 static void fimd_win_commit(struct device *dev, int zpos)
 {
 	struct fimd_context *ctx = get_fimd_context(dev);
@@ -498,21 +520,19 @@ static void fimd_win_commit(struct device *dev, int zpos)
 	unsigned int last_x;
 	unsigned int last_y;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return;
 
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	win_data = &ctx->win_data[win];
 
 	/*
-	 * SHADOWCON register is used for enabling timing.
+	 * SHADOWCON/PRTCON register is used for enabling timing.
 	 *
 	 * for example, once only width value of a register is set,
 	 * if the dma is started then fimd hardware could malfunction so
@@ -522,9 +542,7 @@ static void fimd_win_commit(struct device *dev, int zpos)
 	 */
 
 	/* protect windows */
-	val = readl(ctx->regs + SHADOWCON);
-	val |= SHADOWCON_WINx_PROTECT(win);
-	writel(val, ctx->regs + SHADOWCON);
+	fimd_shadow_protect_win(ctx, win, true);
 
 	/* buffer start address */
 	val = (unsigned long)win_data->dma_addr;
@@ -602,10 +620,13 @@ static void fimd_win_commit(struct device *dev, int zpos)
 	writel(val, ctx->regs + WINCON(win));
 
 	/* Enable DMA channel and unprotect windows */
-	val = readl(ctx->regs + SHADOWCON);
-	val |= SHADOWCON_CHx_ENABLE(win);
-	val &= ~SHADOWCON_WINx_PROTECT(win);
-	writel(val, ctx->regs + SHADOWCON);
+	fimd_shadow_protect_win(ctx, win, false);
+
+	if (ctx->driver_data->has_shadowcon) {
+		val = readl(ctx->regs + SHADOWCON);
+		val |= SHADOWCON_CHx_ENABLE(win);
+		writel(val, ctx->regs + SHADOWCON);
+	}
 
 	win_data->enabled = true;
 }
@@ -617,12 +638,10 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	int win = zpos;
 	u32 val;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	win_data = &ctx->win_data[win];
@@ -634,9 +653,7 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	}
 
 	/* protect windows */
-	val = readl(ctx->regs + SHADOWCON);
-	val |= SHADOWCON_WINx_PROTECT(win);
-	writel(val, ctx->regs + SHADOWCON);
+	fimd_shadow_protect_win(ctx, win, true);
 
 	/* wincon */
 	val = readl(ctx->regs + WINCON(win));
@@ -644,10 +661,13 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	writel(val, ctx->regs + WINCON(win));
 
 	/* unprotect windows */
-	val = readl(ctx->regs + SHADOWCON);
-	val &= ~SHADOWCON_CHx_ENABLE(win);
-	val &= ~SHADOWCON_WINx_PROTECT(win);
-	writel(val, ctx->regs + SHADOWCON);
+	if (ctx->driver_data->has_shadowcon) {
+		val = readl(ctx->regs + SHADOWCON);
+		val &= ~SHADOWCON_CHx_ENABLE(win);
+		writel(val, ctx->regs + SHADOWCON);
+	}
+
+	fimd_shadow_protect_win(ctx, win, false);
 
 	win_data->enabled = false;
 }
@@ -697,8 +717,6 @@ out:
 
 static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * enable drm irq mode.
 	 * - with irq_enabled = 1, we can use the vblank feature.
@@ -725,8 +743,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 
 static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* detach this sub driver from iommu mapping if supported. */
 	if (is_drm_iommu_supported(drm_dev))
 		drm_iommu_detach_device(drm_dev, dev);
@@ -741,8 +757,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx,
 	u32 best_framerate = 0;
 	u32 framerate;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	retrace = timing->left_margin + timing->hsync_len +
 				timing->right_margin + timing->xres;
 	retrace *= timing->upper_margin + timing->vsync_len +
@@ -777,10 +791,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx,
 
 static void fimd_clear_win(struct fimd_context *ctx, int win)
 {
-	u32 val;
-
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	writel(0, ctx->regs + WINCON(win));
 	writel(0, ctx->regs + VIDOSD_A(win));
 	writel(0, ctx->regs + VIDOSD_B(win));
@@ -789,15 +799,11 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
 	if (win == 1 || win == 2)
 		writel(0, ctx->regs + VIDOSD_D(win));
 
-	val = readl(ctx->regs + SHADOWCON);
-	val &= ~SHADOWCON_WINx_PROTECT(win);
-	writel(val, ctx->regs + SHADOWCON);
+	fimd_shadow_protect_win(ctx, win, false);
 }
 
 static int fimd_clock(struct fimd_context *ctx, bool enable)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (enable) {
 		int ret;
 
@@ -883,8 +889,6 @@ static int fimd_probe(struct platform_device *pdev)
 	int win;
 	int ret = -EINVAL;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (dev->of_node) {
 		pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 		if (!pdata) {
@@ -949,6 +953,7 @@ static int fimd_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ctx->driver_data = drm_fimd_get_driver_data(pdev);
 	ctx->vidcon0 = pdata->vidcon0;
 	ctx->vidcon1 = pdata->vidcon1;
 	ctx->default_win = pdata->default_win;
@@ -989,8 +994,6 @@ static int fimd_remove(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct fimd_context *ctx = platform_get_drvdata(pdev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
 	if (ctx->suspended)
@@ -1055,8 +1058,6 @@ static int fimd_runtime_suspend(struct device *dev)
 {
 	struct fimd_context *ctx = get_fimd_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	return fimd_activate(ctx, false);
 }
 
@@ -1064,14 +1065,15 @@ static int fimd_runtime_resume(struct device *dev)
 {
 	struct fimd_context *ctx = get_fimd_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	return fimd_activate(ctx, true);
 }
 #endif
 
 static struct platform_device_id fimd_driver_ids[] = {
 	{
+		.name		= "s3c64xx-fb",
+		.driver_data	= (unsigned long)&s3c64xx_fimd_driver_data,
+	}, {
 		.name		= "exynos4-fb",
 		.driver_data	= (unsigned long)&exynos4_fimd_driver_data,
 	}, {

+ 7 - 11
drivers/gpu/drm/exynos/exynos_drm_g2d.c

@@ -388,12 +388,9 @@ out:
 
 	sg_free_table(g2d_userptr->sgt);
 	kfree(g2d_userptr->sgt);
-	g2d_userptr->sgt = NULL;
 
-	kfree(g2d_userptr->pages);
-	g2d_userptr->pages = NULL;
+	drm_free_large(g2d_userptr->pages);
 	kfree(g2d_userptr);
-	g2d_userptr = NULL;
 }
 
 static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
@@ -463,11 +460,11 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 	npages = (end - start) >> PAGE_SHIFT;
 	g2d_userptr->npages = npages;
 
-	pages = kzalloc(npages * sizeof(struct page *), GFP_KERNEL);
+	pages = drm_calloc_large(npages, sizeof(struct page *));
 	if (!pages) {
 		DRM_ERROR("failed to allocate pages.\n");
-		kfree(g2d_userptr);
-		return ERR_PTR(-ENOMEM);
+		ret = -ENOMEM;
+		goto err_free;
 	}
 
 	vma = find_vma(current->mm, userptr);
@@ -543,7 +540,6 @@ err_sg_free_table:
 
 err_free_sgt:
 	kfree(sgt);
-	sgt = NULL;
 
 err_free_userptr:
 	exynos_gem_put_pages_to_userptr(g2d_userptr->pages,
@@ -554,10 +550,10 @@ err_put_vma:
 	exynos_gem_put_vma(g2d_userptr->vma);
 
 err_free_pages:
-	kfree(pages);
+	drm_free_large(pages);
+
+err_free:
 	kfree(g2d_userptr);
-	pages = NULL;
-	g2d_userptr = NULL;
 
 	return ERR_PTR(ret);
 }

+ 8 - 30
drivers/gpu/drm/exynos/exynos_drm_gem.c

@@ -132,8 +132,6 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
 	struct drm_gem_object *obj;
 	struct exynos_drm_gem_buf *buf;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	obj = &exynos_gem_obj->base;
 	buf = exynos_gem_obj->buffer;
 
@@ -227,7 +225,6 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
 	}
 
 	size = roundup_gem_size(size, flags);
-	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	ret = check_gem_flags(flags);
 	if (ret)
@@ -249,13 +246,14 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
 	exynos_gem_obj->flags = flags;
 
 	ret = exynos_drm_alloc_buf(dev, buf, flags);
-	if (ret < 0) {
-		drm_gem_object_release(&exynos_gem_obj->base);
-		goto err_fini_buf;
-	}
+	if (ret < 0)
+		goto err_gem_fini;
 
 	return exynos_gem_obj;
 
+err_gem_fini:
+	drm_gem_object_release(&exynos_gem_obj->base);
+	kfree(exynos_gem_obj);
 err_fini_buf:
 	exynos_drm_fini_buf(dev, buf);
 	return ERR_PTR(ret);
@@ -268,8 +266,6 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
 	struct exynos_drm_gem_obj *exynos_gem_obj;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
 	if (IS_ERR(exynos_gem_obj))
 		return PTR_ERR(exynos_gem_obj);
@@ -331,8 +327,6 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_exynos_gem_map_off *args = data;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
 			args->handle, (unsigned long)args->offset);
 
@@ -371,8 +365,6 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 	unsigned long vm_size;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_private_data = obj;
 	vma->vm_ops = drm_dev->driver->gem_vm_ops;
@@ -429,9 +421,7 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_exynos_gem_mmap *args = data;
 	struct drm_gem_object *obj;
-	unsigned int addr;
-
-	DRM_DEBUG_KMS("%s\n", __FILE__);
+	unsigned long addr;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM)) {
 		DRM_ERROR("does not support GEM.\n");
@@ -473,14 +463,14 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 
 	drm_gem_object_unreference(obj);
 
-	if (IS_ERR((void *)addr)) {
+	if (IS_ERR_VALUE(addr)) {
 		/* check filp->f_op, filp->private_data are restored */
 		if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
 			file_priv->filp->f_op = fops_get(dev->driver->fops);
 			file_priv->filp->private_data = file_priv;
 		}
 		mutex_unlock(&dev->struct_mutex);
-		return PTR_ERR((void *)addr);
+		return (int)addr;
 	}
 
 	mutex_unlock(&dev->struct_mutex);
@@ -643,8 +633,6 @@ void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
 
 int exynos_drm_gem_init_object(struct drm_gem_object *obj)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	return 0;
 }
 
@@ -653,8 +641,6 @@ void exynos_drm_gem_free_object(struct drm_gem_object *obj)
 	struct exynos_drm_gem_obj *exynos_gem_obj;
 	struct exynos_drm_gem_buf *buf;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_gem_obj = to_exynos_gem_obj(obj);
 	buf = exynos_gem_obj->buffer;
 
@@ -671,8 +657,6 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
 	struct exynos_drm_gem_obj *exynos_gem_obj;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * alocate memory to be used for framebuffer.
 	 * - this callback would be called by user application
@@ -704,8 +688,6 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
 	struct drm_gem_object *obj;
 	int ret = 0;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	mutex_lock(&dev->struct_mutex);
 
 	/*
@@ -743,8 +725,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
 {
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * obj->refcount and obj->handle_count are decreased and
 	 * if both them are 0 then exynos_drm_gem_free_object()
@@ -788,8 +768,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 	struct drm_gem_object *obj;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* set vm_area_struct. */
 	ret = drm_gem_mmap(filp, vma);
 	if (ret < 0) {

+ 41 - 61
drivers/gpu/drm/exynos/exynos_drm_gsc.c

@@ -400,8 +400,6 @@ static int gsc_sw_reset(struct gsc_context *ctx)
 	u32 cfg;
 	int count = GSC_RESET_TIMEOUT;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* s/w reset */
 	cfg = (GSC_SW_RESET_SRESET);
 	gsc_write(cfg, GSC_SW_RESET);
@@ -441,8 +439,6 @@ static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
 {
 	u32 gscblk_cfg;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
 
 	if (enable)
@@ -460,7 +456,7 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
+	DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
 			enable, overflow, done);
 
 	cfg = gsc_read(GSC_IRQ);
@@ -491,7 +487,7 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	cfg = gsc_read(GSC_IN_CON);
 	cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
@@ -567,8 +563,7 @@ static int gsc_src_set_transf(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
-		degree, flip);
+	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
 
 	cfg = gsc_read(GSC_IN_CON);
 	cfg &= ~GSC_IN_ROT_MASK;
@@ -616,8 +611,8 @@ static int gsc_src_set_size(struct device *dev, int swap,
 	struct gsc_scaler *sc = &ctx->sc;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
-		__func__, swap, pos->x, pos->y, pos->w, pos->h);
+	DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
+		swap, pos->x, pos->y, pos->w, pos->h);
 
 	if (swap) {
 		img_pos.w = pos->h;
@@ -634,8 +629,7 @@ static int gsc_src_set_size(struct device *dev, int swap,
 		GSC_CROPPED_HEIGHT(img_pos.h));
 	gsc_write(cfg, GSC_CROPPED_SIZE);
 
-	DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
-		__func__, sz->hsize, sz->vsize);
+	DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize);
 
 	/* original size */
 	cfg = gsc_read(GSC_SRCIMG_SIZE);
@@ -650,8 +644,7 @@ static int gsc_src_set_size(struct device *dev, int swap,
 	cfg = gsc_read(GSC_IN_CON);
 	cfg &= ~GSC_IN_RGB_TYPE_MASK;
 
-	DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
-		__func__, pos->w, sc->range);
+	DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range);
 
 	if (pos->w >= GSC_WIDTH_ITU_709)
 		if (sc->range)
@@ -677,8 +670,7 @@ static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
 	u32 cfg;
 	u32 mask = 0x00000001 << buf_id;
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
-		buf_id, buf_type);
+	DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
 
 	/* mask register set */
 	cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
@@ -721,7 +713,7 @@ static int gsc_src_set_addr(struct device *dev,
 
 	property = &c_node->property;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
+	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
 		property->prop_id, buf_id, buf_type);
 
 	if (buf_id > GSC_MAX_SRC) {
@@ -765,7 +757,7 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
+	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
 
 	cfg = gsc_read(GSC_OUT_CON);
 	cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
@@ -838,8 +830,7 @@ static int gsc_dst_set_transf(struct device *dev,
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
-		degree, flip);
+	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
 
 	cfg = gsc_read(GSC_IN_CON);
 	cfg &= ~GSC_IN_ROT_MASK;
@@ -881,7 +872,7 @@ static int gsc_dst_set_transf(struct device *dev,
 
 static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio)
 {
-	DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
+	DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst);
 
 	if (src >= dst * 8) {
 		DRM_ERROR("failed to make ratio and shift.\n");
@@ -944,20 +935,19 @@ static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc,
 		return ret;
 	}
 
-	DRM_DEBUG_KMS("%s:pre_hratio[%d]pre_vratio[%d]\n",
-		__func__, sc->pre_hratio, sc->pre_vratio);
+	DRM_DEBUG_KMS("pre_hratio[%d]pre_vratio[%d]\n",
+		sc->pre_hratio, sc->pre_vratio);
 
 	sc->main_hratio = (src_w << 16) / dst_w;
 	sc->main_vratio = (src_h << 16) / dst_h;
 
-	DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
-		__func__, sc->main_hratio, sc->main_vratio);
+	DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n",
+		sc->main_hratio, sc->main_vratio);
 
 	gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio,
 		&sc->pre_shfactor);
 
-	DRM_DEBUG_KMS("%s:pre_shfactor[%d]\n", __func__,
-		sc->pre_shfactor);
+	DRM_DEBUG_KMS("pre_shfactor[%d]\n", sc->pre_shfactor);
 
 	cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) |
 		GSC_PRESC_H_RATIO(sc->pre_hratio) |
@@ -1023,8 +1013,8 @@ static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc)
 {
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
-		__func__, sc->main_hratio, sc->main_vratio);
+	DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n",
+		sc->main_hratio, sc->main_vratio);
 
 	gsc_set_h_coef(ctx, sc->main_hratio);
 	cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
@@ -1043,8 +1033,8 @@ static int gsc_dst_set_size(struct device *dev, int swap,
 	struct gsc_scaler *sc = &ctx->sc;
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
-		__func__, swap, pos->x, pos->y, pos->w, pos->h);
+	DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
+		swap, pos->x, pos->y, pos->w, pos->h);
 
 	if (swap) {
 		img_pos.w = pos->h;
@@ -1060,8 +1050,7 @@ static int gsc_dst_set_size(struct device *dev, int swap,
 	cfg = (GSC_SCALED_WIDTH(img_pos.w) | GSC_SCALED_HEIGHT(img_pos.h));
 	gsc_write(cfg, GSC_SCALED_SIZE);
 
-	DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
-		__func__, sz->hsize, sz->vsize);
+	DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize);
 
 	/* original size */
 	cfg = gsc_read(GSC_DSTIMG_SIZE);
@@ -1074,8 +1063,7 @@ static int gsc_dst_set_size(struct device *dev, int swap,
 	cfg = gsc_read(GSC_OUT_CON);
 	cfg &= ~GSC_OUT_RGB_TYPE_MASK;
 
-	DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
-		__func__, pos->w, sc->range);
+	DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range);
 
 	if (pos->w >= GSC_WIDTH_ITU_709)
 		if (sc->range)
@@ -1104,7 +1092,7 @@ static int gsc_dst_get_buf_seq(struct gsc_context *ctx)
 		if (cfg & (mask << i))
 			buf_num--;
 
-	DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
+	DRM_DEBUG_KMS("buf_num[%d]\n", buf_num);
 
 	return buf_num;
 }
@@ -1118,8 +1106,7 @@ static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
 	u32 mask = 0x00000001 << buf_id;
 	int ret = 0;
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
-		buf_id, buf_type);
+	DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
 
 	mutex_lock(&ctx->lock);
 
@@ -1177,7 +1164,7 @@ static int gsc_dst_set_addr(struct device *dev,
 
 	property = &c_node->property;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
+	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
 		property->prop_id, buf_id, buf_type);
 
 	if (buf_id > GSC_MAX_DST) {
@@ -1217,7 +1204,7 @@ static struct exynos_drm_ipp_ops gsc_dst_ops = {
 
 static int gsc_clk_ctrl(struct gsc_context *ctx, bool enable)
 {
-	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	if (enable) {
 		clk_enable(ctx->gsc_clk);
@@ -1236,7 +1223,7 @@ static int gsc_get_src_buf_index(struct gsc_context *ctx)
 	u32 buf_id = GSC_MAX_SRC;
 	int ret;
 
-	DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
 
 	cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
 	curr_index = GSC_IN_CURR_GET_INDEX(cfg);
@@ -1259,7 +1246,7 @@ static int gsc_get_src_buf_index(struct gsc_context *ctx)
 		return ret;
 	}
 
-	DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
+	DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg,
 		curr_index, buf_id);
 
 	return buf_id;
@@ -1271,7 +1258,7 @@ static int gsc_get_dst_buf_index(struct gsc_context *ctx)
 	u32 buf_id = GSC_MAX_DST;
 	int ret;
 
-	DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
 
 	cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
 	curr_index = GSC_OUT_CURR_GET_INDEX(cfg);
@@ -1294,7 +1281,7 @@ static int gsc_get_dst_buf_index(struct gsc_context *ctx)
 		return ret;
 	}
 
-	DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
+	DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg,
 		curr_index, buf_id);
 
 	return buf_id;
@@ -1310,7 +1297,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
 	u32 status;
 	int buf_id[EXYNOS_DRM_OPS_MAX];
 
-	DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
 
 	status = gsc_read(GSC_IRQ);
 	if (status & GSC_IRQ_STATUS_OR_IRQ) {
@@ -1331,7 +1318,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
 		if (buf_id[EXYNOS_DRM_OPS_DST] < 0)
 			return IRQ_HANDLED;
 
-		DRM_DEBUG_KMS("%s:buf_id_src[%d]buf_id_dst[%d]\n", __func__,
+		DRM_DEBUG_KMS("buf_id_src[%d]buf_id_dst[%d]\n",
 			buf_id[EXYNOS_DRM_OPS_SRC], buf_id[EXYNOS_DRM_OPS_DST]);
 
 		event_work->ippdrv = ippdrv;
@@ -1350,8 +1337,6 @@ static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
 {
 	struct drm_exynos_ipp_prop_list *prop_list;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
 	if (!prop_list) {
 		DRM_ERROR("failed to alloc property list.\n");
@@ -1394,7 +1379,7 @@ static inline bool gsc_check_drm_flip(enum drm_exynos_flip flip)
 	case EXYNOS_DRM_FLIP_BOTH:
 		return true;
 	default:
-		DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+		DRM_DEBUG_KMS("invalid flip\n");
 		return false;
 	}
 }
@@ -1411,8 +1396,6 @@ static int gsc_ippdrv_check_property(struct device *dev,
 	bool swap;
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	for_each_ipp_ops(i) {
 		if ((i == EXYNOS_DRM_OPS_SRC) &&
 			(property->cmd == IPP_CMD_WB))
@@ -1521,8 +1504,6 @@ static int gsc_ippdrv_reset(struct device *dev)
 	struct gsc_scaler *sc = &ctx->sc;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* reset h/w block */
 	ret = gsc_sw_reset(ctx);
 	if (ret < 0) {
@@ -1549,7 +1530,7 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	u32 cfg;
 	int ret, i;
 
-	DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
 
 	if (!c_node) {
 		DRM_ERROR("failed to get c_node.\n");
@@ -1643,7 +1624,7 @@ static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	struct drm_exynos_ipp_set_wb set_wb = {0, 0};
 	u32 cfg;
 
-	DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
+	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
 
 	switch (cmd) {
 	case IPP_CMD_M2M:
@@ -1728,8 +1709,7 @@ static int gsc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
-		(int)ippdrv);
+	DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
 
 	mutex_init(&ctx->lock);
 	platform_set_drvdata(pdev, ctx);
@@ -1772,7 +1752,7 @@ static int gsc_suspend(struct device *dev)
 {
 	struct gsc_context *ctx = get_gsc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	if (pm_runtime_suspended(dev))
 		return 0;
@@ -1784,7 +1764,7 @@ static int gsc_resume(struct device *dev)
 {
 	struct gsc_context *ctx = get_gsc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	if (!pm_runtime_suspended(dev))
 		return gsc_clk_ctrl(ctx, true);
@@ -1798,7 +1778,7 @@ static int gsc_runtime_suspend(struct device *dev)
 {
 	struct gsc_context *ctx = get_gsc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	return  gsc_clk_ctrl(ctx, false);
 }
@@ -1807,7 +1787,7 @@ static int gsc_runtime_resume(struct device *dev)
 {
 	struct gsc_context *ctx = get_gsc_context(dev);
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __FILE__, ctx->id);
+	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
 
 	return  gsc_clk_ctrl(ctx, true);
 }

+ 11 - 52
drivers/gpu/drm/exynos/exynos_drm_hdmi.c

@@ -88,16 +88,12 @@ void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
 
 void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ops)
 		hdmi_ops = ops;
 }
 
 void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ops)
 		mixer_ops = ops;
 }
@@ -106,8 +102,6 @@ static bool drm_hdmi_is_connected(struct device *dev)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->is_connected)
 		return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
 
@@ -119,34 +113,31 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->get_edid)
 		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
 
 	return NULL;
 }
 
-static int drm_hdmi_check_timing(struct device *dev, void *timing)
+static int drm_hdmi_check_mode(struct device *dev,
+		struct drm_display_mode *mode)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 	int ret = 0;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	* Both, mixer and hdmi should be able to handle the requested mode.
 	* If any of the two fails, return mode as BAD.
 	*/
 
-	if (mixer_ops && mixer_ops->check_timing)
-		ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);
+	if (mixer_ops && mixer_ops->check_mode)
+		ret = mixer_ops->check_mode(ctx->mixer_ctx->ctx, mode);
 
 	if (ret)
 		return ret;
 
-	if (hdmi_ops && hdmi_ops->check_timing)
-		return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
+	if (hdmi_ops && hdmi_ops->check_mode)
+		return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
 
 	return 0;
 }
@@ -155,8 +146,6 @@ static int drm_hdmi_power_on(struct device *dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->power_on)
 		return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
 
@@ -167,7 +156,7 @@ static struct exynos_drm_display_ops drm_hdmi_display_ops = {
 	.type = EXYNOS_DISPLAY_TYPE_HDMI,
 	.is_connected = drm_hdmi_is_connected,
 	.get_edid = drm_hdmi_get_edid,
-	.check_timing = drm_hdmi_check_timing,
+	.check_mode = drm_hdmi_check_mode,
 	.power_on = drm_hdmi_power_on,
 };
 
@@ -177,8 +166,6 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
 	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
 	struct exynos_drm_manager *manager = subdrv->manager;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (mixer_ops && mixer_ops->enable_vblank)
 		return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
 						manager->pipe);
@@ -190,8 +177,6 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (mixer_ops && mixer_ops->disable_vblank)
 		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
 }
@@ -200,8 +185,6 @@ static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (mixer_ops && mixer_ops->wait_for_vblank)
 		mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
 }
@@ -214,11 +197,9 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
 	struct drm_display_mode *m;
 	int mode_ok;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	mode_ok = drm_hdmi_check_timing(subdrv_dev, adjusted_mode);
+	mode_ok = drm_hdmi_check_mode(subdrv_dev, adjusted_mode);
 
 	/* just return if user desired mode exists. */
 	if (mode_ok == 0)
@@ -229,7 +210,7 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
 	 * to adjusted_mode.
 	 */
 	list_for_each_entry(m, &connector->modes, head) {
-		mode_ok = drm_hdmi_check_timing(subdrv_dev, m);
+		mode_ok = drm_hdmi_check_mode(subdrv_dev, m);
 
 		if (mode_ok == 0) {
 			struct drm_mode_object base;
@@ -256,8 +237,6 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->mode_set)
 		hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
 }
@@ -267,8 +246,6 @@ static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->get_max_resol)
 		hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
 }
@@ -277,8 +254,6 @@ static void drm_hdmi_commit(struct device *subdrv_dev)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (hdmi_ops && hdmi_ops->commit)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
@@ -287,8 +262,6 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (mixer_ops && mixer_ops->dpms)
 		mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
 
@@ -301,8 +274,6 @@ static void drm_hdmi_apply(struct device *subdrv_dev)
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	for (i = 0; i < MIXER_WIN_NR; i++) {
 		if (!ctx->enabled[i])
 			continue;
@@ -331,8 +302,6 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (mixer_ops && mixer_ops->win_mode_set)
 		mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
 }
@@ -342,9 +311,7 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	if (win < 0 || win > MIXER_WIN_NR) {
+	if (win < 0 || win >= MIXER_WIN_NR) {
 		DRM_ERROR("mixer window[%d] is wrong\n", win);
 		return;
 	}
@@ -360,9 +327,7 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	if (win < 0 || win > MIXER_WIN_NR) {
+	if (win < 0 || win >= MIXER_WIN_NR) {
 		DRM_ERROR("mixer window[%d] is wrong\n", win);
 		return;
 	}
@@ -392,8 +357,6 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
 	struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
 	struct drm_hdmi_context *ctx;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!hdmi_ctx) {
 		DRM_ERROR("hdmi context not initialized.\n");
 		return -EFAULT;
@@ -440,8 +403,6 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 	struct exynos_drm_subdrv *subdrv;
 	struct drm_hdmi_context *ctx;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx) {
 		DRM_LOG_KMS("failed to alloc common hdmi context.\n");
@@ -466,8 +427,6 @@ static int exynos_drm_hdmi_remove(struct platform_device *pdev)
 {
 	struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
 	return 0;

+ 3 - 3
drivers/gpu/drm/exynos/exynos_drm_hdmi.h

@@ -32,11 +32,11 @@ struct exynos_hdmi_ops {
 	bool (*is_connected)(void *ctx);
 	struct edid *(*get_edid)(void *ctx,
 			struct drm_connector *connector);
-	int (*check_timing)(void *ctx, struct fb_videomode *timing);
+	int (*check_mode)(void *ctx, struct drm_display_mode *mode);
 	int (*power_on)(void *ctx, int mode);
 
 	/* manager */
-	void (*mode_set)(void *ctx, void *mode);
+	void (*mode_set)(void *ctx, struct drm_display_mode *mode);
 	void (*get_max_resol)(void *ctx, unsigned int *width,
 				unsigned int *height);
 	void (*commit)(void *ctx);
@@ -57,7 +57,7 @@ struct exynos_mixer_ops {
 	void (*win_disable)(void *ctx, int zpos);
 
 	/* display */
-	int (*check_timing)(void *ctx, struct fb_videomode *timing);
+	int (*check_mode)(void *ctx, struct drm_display_mode *mode);
 };
 
 void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);

+ 67 - 135
drivers/gpu/drm/exynos/exynos_drm_ipp.c

@@ -131,8 +131,6 @@ void exynos_platform_device_ipp_unregister(void)
 
 int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!ippdrv)
 		return -EINVAL;
 
@@ -145,8 +143,6 @@ int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
 
 int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!ippdrv)
 		return -EINVAL;
 
@@ -162,8 +158,6 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
 {
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* do the allocation under our mutexlock */
 	mutex_lock(lock);
 	ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
@@ -179,7 +173,7 @@ static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
 {
 	void *obj;
 
-	DRM_DEBUG_KMS("%s:id[%d]\n", __func__, id);
+	DRM_DEBUG_KMS("id[%d]\n", id);
 
 	mutex_lock(lock);
 
@@ -216,7 +210,7 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
 	struct exynos_drm_ippdrv *ippdrv;
 	u32 ipp_id = property->ipp_id;
 
-	DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ipp_id);
+	DRM_DEBUG_KMS("ipp_id[%d]\n", ipp_id);
 
 	if (ipp_id) {
 		/* find ipp driver using idr */
@@ -257,14 +251,13 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
 		 */
 		list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
 			if (ipp_check_dedicated(ippdrv, property->cmd)) {
-				DRM_DEBUG_KMS("%s:used device.\n", __func__);
+				DRM_DEBUG_KMS("used device.\n");
 				continue;
 			}
 
 			if (ippdrv->check_property &&
 			    ippdrv->check_property(ippdrv->dev, property)) {
-				DRM_DEBUG_KMS("%s:not support property.\n",
-					__func__);
+				DRM_DEBUG_KMS("not support property.\n");
 				continue;
 			}
 
@@ -283,10 +276,10 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
 	struct drm_exynos_ipp_cmd_node *c_node;
 	int count = 0;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+	DRM_DEBUG_KMS("prop_id[%d]\n", prop_id);
 
 	if (list_empty(&exynos_drm_ippdrv_list)) {
-		DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
+		DRM_DEBUG_KMS("ippdrv_list is empty.\n");
 		return ERR_PTR(-ENODEV);
 	}
 
@@ -296,8 +289,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
 	 * e.g PAUSE state, queue buf, command contro.
 	 */
 	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
-		DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n", __func__,
-			count++, (int)ippdrv);
+		DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv);
 
 		if (!list_empty(&ippdrv->cmd_list)) {
 			list_for_each_entry(c_node, &ippdrv->cmd_list, list)
@@ -320,8 +312,6 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
 	struct exynos_drm_ippdrv *ippdrv;
 	int count = 0;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!ctx) {
 		DRM_ERROR("invalid context.\n");
 		return -EINVAL;
@@ -332,7 +322,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, prop_list->ipp_id);
+	DRM_DEBUG_KMS("ipp_id[%d]\n", prop_list->ipp_id);
 
 	if (!prop_list->ipp_id) {
 		list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list)
@@ -371,11 +361,11 @@ static void ipp_print_property(struct drm_exynos_ipp_property *property,
 	struct drm_exynos_pos *pos = &config->pos;
 	struct drm_exynos_sz *sz = &config->sz;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]ops[%s]fmt[0x%x]\n",
-		__func__, property->prop_id, idx ? "dst" : "src", config->fmt);
+	DRM_DEBUG_KMS("prop_id[%d]ops[%s]fmt[0x%x]\n",
+		property->prop_id, idx ? "dst" : "src", config->fmt);
 
-	DRM_DEBUG_KMS("%s:pos[%d %d %d %d]sz[%d %d]f[%d]r[%d]\n",
-		__func__, pos->x, pos->y, pos->w, pos->h,
+	DRM_DEBUG_KMS("pos[%d %d %d %d]sz[%d %d]f[%d]r[%d]\n",
+		pos->x, pos->y, pos->w, pos->h,
 		sz->hsize, sz->vsize, config->flip, config->degree);
 }
 
@@ -385,7 +375,7 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
 	struct drm_exynos_ipp_cmd_node *c_node;
 	u32 prop_id = property->prop_id;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
+	DRM_DEBUG_KMS("prop_id[%d]\n", prop_id);
 
 	ippdrv = ipp_find_drv_by_handle(prop_id);
 	if (IS_ERR(ippdrv)) {
@@ -401,8 +391,8 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
 	list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
 		if ((c_node->property.prop_id == prop_id) &&
 		    (c_node->state == IPP_STATE_STOP)) {
-			DRM_DEBUG_KMS("%s:found cmd[%d]ippdrv[0x%x]\n",
-				__func__, property->cmd, (int)ippdrv);
+			DRM_DEBUG_KMS("found cmd[%d]ippdrv[0x%x]\n",
+				property->cmd, (int)ippdrv);
 
 			c_node->property = *property;
 			return 0;
@@ -418,8 +408,6 @@ static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void)
 {
 	struct drm_exynos_ipp_cmd_work *cmd_work;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL);
 	if (!cmd_work) {
 		DRM_ERROR("failed to alloc cmd_work.\n");
@@ -435,8 +423,6 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
 {
 	struct drm_exynos_ipp_event_work *event_work;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	event_work = kzalloc(sizeof(*event_work), GFP_KERNEL);
 	if (!event_work) {
 		DRM_ERROR("failed to alloc event_work.\n");
@@ -460,8 +446,6 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
 	struct drm_exynos_ipp_cmd_node *c_node;
 	int ret, i;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!ctx) {
 		DRM_ERROR("invalid context.\n");
 		return -EINVAL;
@@ -486,7 +470,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
 	 * instead of allocation.
 	 */
 	if (property->prop_id) {
-		DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+		DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
 		return ipp_find_and_set_property(property);
 	}
 
@@ -512,8 +496,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
 		goto err_clear;
 	}
 
-	DRM_DEBUG_KMS("%s:created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
-		__func__, property->prop_id, property->cmd, (int)ippdrv);
+	DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
+		property->prop_id, property->cmd, (int)ippdrv);
 
 	/* stored property information and ippdrv in private data */
 	c_node->priv = priv;
@@ -569,8 +553,6 @@ err_clear:
 
 static void ipp_clean_cmd_node(struct drm_exynos_ipp_cmd_node *c_node)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* delete list */
 	list_del(&c_node->list);
 
@@ -593,8 +575,6 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
 	struct list_head *head;
 	int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, };
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	mutex_lock(&c_node->mem_lock);
 
 	for_each_ipp_ops(i) {
@@ -602,20 +582,19 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
 		head = &c_node->mem_list[i];
 
 		if (list_empty(head)) {
-			DRM_DEBUG_KMS("%s:%s memory empty.\n", __func__,
-				i ? "dst" : "src");
+			DRM_DEBUG_KMS("%s memory empty.\n", i ? "dst" : "src");
 			continue;
 		}
 
 		/* find memory node entry */
 		list_for_each_entry(m_node, head, list) {
-			DRM_DEBUG_KMS("%s:%s,count[%d]m_node[0x%x]\n", __func__,
+			DRM_DEBUG_KMS("%s,count[%d]m_node[0x%x]\n",
 				i ? "dst" : "src", count[i], (int)m_node);
 			count[i]++;
 		}
 	}
 
-	DRM_DEBUG_KMS("%s:min[%d]max[%d]\n", __func__,
+	DRM_DEBUG_KMS("min[%d]max[%d]\n",
 		min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
 		max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
 
@@ -644,15 +623,14 @@ static struct drm_exynos_ipp_mem_node
 	struct list_head *head;
 	int count = 0;
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, qbuf->buf_id);
+	DRM_DEBUG_KMS("buf_id[%d]\n", qbuf->buf_id);
 
 	/* source/destination memory list */
 	head = &c_node->mem_list[qbuf->ops_id];
 
 	/* find memory node from memory list */
 	list_for_each_entry(m_node, head, list) {
-		DRM_DEBUG_KMS("%s:count[%d]m_node[0x%x]\n",
-			__func__, count++, (int)m_node);
+		DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node);
 
 		/* compare buffer id */
 		if (m_node->buf_id == qbuf->buf_id)
@@ -669,7 +647,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
 	struct exynos_drm_ipp_ops *ops = NULL;
 	int ret = 0;
 
-	DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
+	DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
 
 	if (!m_node) {
 		DRM_ERROR("invalid queue node.\n");
@@ -678,7 +656,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
 
 	mutex_lock(&c_node->mem_lock);
 
-	DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
+	DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
 
 	/* get operations callback */
 	ops = ippdrv->ops[m_node->ops_id];
@@ -714,8 +692,6 @@ static struct drm_exynos_ipp_mem_node
 	void *addr;
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	mutex_lock(&c_node->mem_lock);
 
 	m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
@@ -732,14 +708,11 @@ static struct drm_exynos_ipp_mem_node
 	m_node->prop_id = qbuf->prop_id;
 	m_node->buf_id = qbuf->buf_id;
 
-	DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__,
-		(int)m_node, qbuf->ops_id);
-	DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]\n", __func__,
-		qbuf->prop_id, m_node->buf_id);
+	DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id);
+	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
 
 	for_each_ipp_planar(i) {
-		DRM_DEBUG_KMS("%s:i[%d]handle[0x%x]\n", __func__,
-			i, qbuf->handle[i]);
+		DRM_DEBUG_KMS("i[%d]handle[0x%x]\n", i, qbuf->handle[i]);
 
 		/* get dma address by handle */
 		if (qbuf->handle[i]) {
@@ -752,9 +725,8 @@ static struct drm_exynos_ipp_mem_node
 
 			buf_info.handles[i] = qbuf->handle[i];
 			buf_info.base[i] = *(dma_addr_t *) addr;
-			DRM_DEBUG_KMS("%s:i[%d]base[0x%x]hd[0x%x]\n",
-				__func__, i, buf_info.base[i],
-				(int)buf_info.handles[i]);
+			DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%x]\n",
+				i, buf_info.base[i], (int)buf_info.handles[i]);
 		}
 	}
 
@@ -778,7 +750,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
 {
 	int i;
 
-	DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
+	DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
 
 	if (!m_node) {
 		DRM_ERROR("invalid dequeue node.\n");
@@ -792,7 +764,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
 
 	mutex_lock(&c_node->mem_lock);
 
-	DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
+	DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
 
 	/* put gem buffer */
 	for_each_ipp_planar(i) {
@@ -824,8 +796,7 @@ static int ipp_get_event(struct drm_device *drm_dev,
 	struct drm_exynos_ipp_send_event *e;
 	unsigned long flags;
 
-	DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
-		qbuf->ops_id, qbuf->buf_id);
+	DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id);
 
 	e = kzalloc(sizeof(*e), GFP_KERNEL);
 
@@ -857,16 +828,13 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
 	struct drm_exynos_ipp_send_event *e, *te;
 	int count = 0;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (list_empty(&c_node->event_list)) {
-		DRM_DEBUG_KMS("%s:event_list is empty.\n", __func__);
+		DRM_DEBUG_KMS("event_list is empty.\n");
 		return;
 	}
 
 	list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
-		DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
-			__func__, count++, (int)e);
+		DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e);
 
 		/*
 		 * quf == NULL condition means all event deletion.
@@ -912,8 +880,6 @@ static int ipp_queue_buf_with_run(struct device *dev,
 	struct exynos_drm_ipp_ops *ops;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	ippdrv = ipp_find_drv_by_handle(qbuf->prop_id);
 	if (IS_ERR(ippdrv)) {
 		DRM_ERROR("failed to get ipp driver.\n");
@@ -929,12 +895,12 @@ static int ipp_queue_buf_with_run(struct device *dev,
 	property = &c_node->property;
 
 	if (c_node->state != IPP_STATE_START) {
-		DRM_DEBUG_KMS("%s:bypass for invalid state.\n" , __func__);
+		DRM_DEBUG_KMS("bypass for invalid state.\n");
 		return 0;
 	}
 
 	if (!ipp_check_mem_list(c_node)) {
-		DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
+		DRM_DEBUG_KMS("empty memory.\n");
 		return 0;
 	}
 
@@ -964,8 +930,6 @@ static void ipp_clean_queue_buf(struct drm_device *drm_dev,
 {
 	struct drm_exynos_ipp_mem_node *m_node, *tm_node;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!list_empty(&c_node->mem_list[qbuf->ops_id])) {
 		/* delete list */
 		list_for_each_entry_safe(m_node, tm_node,
@@ -989,8 +953,6 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
 	struct drm_exynos_ipp_mem_node *m_node;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!qbuf) {
 		DRM_ERROR("invalid buf parameter.\n");
 		return -EINVAL;
@@ -1001,8 +963,8 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]ops_id[%s]buf_id[%d]buf_type[%d]\n",
-		__func__, qbuf->prop_id, qbuf->ops_id ? "dst" : "src",
+	DRM_DEBUG_KMS("prop_id[%d]ops_id[%s]buf_id[%d]buf_type[%d]\n",
+		qbuf->prop_id, qbuf->ops_id ? "dst" : "src",
 		qbuf->buf_id, qbuf->buf_type);
 
 	/* find command node */
@@ -1075,8 +1037,6 @@ err_clean_node:
 static bool exynos_drm_ipp_check_valid(struct device *dev,
 		enum drm_exynos_ipp_ctrl ctrl, enum drm_exynos_ipp_state state)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (ctrl != IPP_CTRL_PLAY) {
 		if (pm_runtime_suspended(dev)) {
 			DRM_ERROR("pm:runtime_suspended.\n");
@@ -1104,7 +1064,6 @@ static bool exynos_drm_ipp_check_valid(struct device *dev,
 	default:
 		DRM_ERROR("invalid state.\n");
 		goto err_status;
-		break;
 	}
 
 	return true;
@@ -1126,8 +1085,6 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 	struct drm_exynos_ipp_cmd_work *cmd_work;
 	struct drm_exynos_ipp_cmd_node *c_node;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!ctx) {
 		DRM_ERROR("invalid context.\n");
 		return -EINVAL;
@@ -1138,7 +1095,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:ctrl[%d]prop_id[%d]\n", __func__,
+	DRM_DEBUG_KMS("ctrl[%d]prop_id[%d]\n",
 		cmd_ctrl->ctrl, cmd_ctrl->prop_id);
 
 	ippdrv = ipp_find_drv_by_handle(cmd_ctrl->prop_id);
@@ -1213,7 +1170,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:done ctrl[%d]prop_id[%d]\n", __func__,
+	DRM_DEBUG_KMS("done ctrl[%d]prop_id[%d]\n",
 		cmd_ctrl->ctrl, cmd_ctrl->prop_id);
 
 	return 0;
@@ -1249,7 +1206,7 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+	DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
 
 	/* reset h/w block */
 	if (ippdrv->reset &&
@@ -1310,13 +1267,13 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
 	struct list_head *head;
 	int ret, i;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+	DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
 
 	/* store command info in ippdrv */
 	ippdrv->c_node = c_node;
 
 	if (!ipp_check_mem_list(c_node)) {
-		DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
+		DRM_DEBUG_KMS("empty memory.\n");
 		return -ENOMEM;
 	}
 
@@ -1343,8 +1300,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
 				return ret;
 			}
 
-			DRM_DEBUG_KMS("%s:m_node[0x%x]\n",
-				__func__, (int)m_node);
+			DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
 
 			ret = ipp_set_mem_node(ippdrv, c_node, m_node);
 			if (ret) {
@@ -1382,7 +1338,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
 		return -EINVAL;
 	}
 
-	DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, property->cmd);
+	DRM_DEBUG_KMS("cmd[%d]\n", property->cmd);
 
 	/* start operations */
 	if (ippdrv->start) {
@@ -1405,7 +1361,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
 	struct list_head *head;
 	int ret = 0, i;
 
-	DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
+	DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
 
 	/* put event */
 	ipp_put_event(c_node, NULL);
@@ -1418,8 +1374,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
 			head = &c_node->mem_list[i];
 
 			if (list_empty(head)) {
-				DRM_DEBUG_KMS("%s:mem_list is empty.\n",
-					__func__);
+				DRM_DEBUG_KMS("mem_list is empty.\n");
 				break;
 			}
 
@@ -1439,7 +1394,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
 		head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
 
 		if (list_empty(head)) {
-			DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
+			DRM_DEBUG_KMS("mem_list is empty.\n");
 			break;
 		}
 
@@ -1456,7 +1411,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
 		head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
 
 		if (list_empty(head)) {
-			DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
+			DRM_DEBUG_KMS("mem_list is empty.\n");
 			break;
 		}
 
@@ -1491,8 +1446,6 @@ void ipp_sched_cmd(struct work_struct *work)
 	struct drm_exynos_ipp_property *property;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	ippdrv = cmd_work->ippdrv;
 	if (!ippdrv) {
 		DRM_ERROR("invalid ippdrv list.\n");
@@ -1550,7 +1503,7 @@ void ipp_sched_cmd(struct work_struct *work)
 		break;
 	}
 
-	DRM_DEBUG_KMS("%s:ctrl[%d] done.\n", __func__, cmd_work->ctrl);
+	DRM_DEBUG_KMS("ctrl[%d] done.\n", cmd_work->ctrl);
 
 err_unlock:
 	mutex_unlock(&c_node->cmd_lock);
@@ -1571,8 +1524,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 	int ret, i;
 
 	for_each_ipp_ops(i)
-		DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
-			i ? "dst" : "src", buf_id[i]);
+		DRM_DEBUG_KMS("%s buf_id[%d]\n", i ? "dst" : "src", buf_id[i]);
 
 	if (!drm_dev) {
 		DRM_ERROR("failed to get drm_dev.\n");
@@ -1585,12 +1537,12 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 	}
 
 	if (list_empty(&c_node->event_list)) {
-		DRM_DEBUG_KMS("%s:event list is empty.\n", __func__);
+		DRM_DEBUG_KMS("event list is empty.\n");
 		return 0;
 	}
 
 	if (!ipp_check_mem_list(c_node)) {
-		DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
+		DRM_DEBUG_KMS("empty memory.\n");
 		return 0;
 	}
 
@@ -1609,7 +1561,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 			}
 
 			tbuf_id[i] = m_node->buf_id;
-			DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
+			DRM_DEBUG_KMS("%s buf_id[%d]\n",
 				i ? "dst" : "src", tbuf_id[i]);
 
 			ret = ipp_put_mem_node(drm_dev, c_node, m_node);
@@ -1677,8 +1629,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 	}
 
 	do_gettimeofday(&now);
-	DRM_DEBUG_KMS("%s:tv_sec[%ld]tv_usec[%ld]\n"
-		, __func__, now.tv_sec, now.tv_usec);
+	DRM_DEBUG_KMS("tv_sec[%ld]tv_usec[%ld]\n", now.tv_sec, now.tv_usec);
 	e->event.tv_sec = now.tv_sec;
 	e->event.tv_usec = now.tv_usec;
 	e->event.prop_id = property->prop_id;
@@ -1692,7 +1643,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
 	wake_up_interruptible(&e->base.file_priv->event_wait);
 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 
-	DRM_DEBUG_KMS("%s:done cmd[%d]prop_id[%d]buf_id[%d]\n", __func__,
+	DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n",
 		property->cmd, property->prop_id, tbuf_id[EXYNOS_DRM_OPS_DST]);
 
 	return 0;
@@ -1711,8 +1662,7 @@ void ipp_sched_event(struct work_struct *work)
 		return;
 	}
 
-	DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__,
-		event_work->buf_id[EXYNOS_DRM_OPS_DST]);
+	DRM_DEBUG_KMS("buf_id[%d]\n", event_work->buf_id[EXYNOS_DRM_OPS_DST]);
 
 	ippdrv = event_work->ippdrv;
 	if (!ippdrv) {
@@ -1733,8 +1683,8 @@ void ipp_sched_event(struct work_struct *work)
 	 * or going out operations.
 	 */
 	if (c_node->state != IPP_STATE_START) {
-		DRM_DEBUG_KMS("%s:bypass state[%d]prop_id[%d]\n",
-			__func__, c_node->state, c_node->property.prop_id);
+		DRM_DEBUG_KMS("bypass state[%d]prop_id[%d]\n",
+			c_node->state, c_node->property.prop_id);
 		goto err_completion;
 	}
 
@@ -1759,8 +1709,6 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 	struct exynos_drm_ippdrv *ippdrv;
 	int ret, count = 0;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* get ipp driver entry */
 	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
 		ippdrv->drm_dev = drm_dev;
@@ -1772,7 +1720,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 			goto err_idr;
 		}
 
-		DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]ipp_id[%d]\n", __func__,
+		DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
 			count++, (int)ippdrv, ippdrv->ipp_id);
 
 		if (ippdrv->ipp_id == 0) {
@@ -1816,8 +1764,6 @@ static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 {
 	struct exynos_drm_ippdrv *ippdrv;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* get ipp driver entry */
 	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
 		if (is_drm_iommu_supported(drm_dev))
@@ -1834,8 +1780,6 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
 	struct drm_exynos_file_private *file_priv = file->driver_priv;
 	struct exynos_drm_ipp_private *priv;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		DRM_ERROR("failed to allocate priv.\n");
@@ -1846,7 +1790,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
 
 	INIT_LIST_HEAD(&priv->event_list);
 
-	DRM_DEBUG_KMS("%s:done priv[0x%x]\n", __func__, (int)priv);
+	DRM_DEBUG_KMS("done priv[0x%x]\n", (int)priv);
 
 	return 0;
 }
@@ -1860,10 +1804,10 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
 	struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
 	int count = 0;
 
-	DRM_DEBUG_KMS("%s:for priv[0x%x]\n", __func__, (int)priv);
+	DRM_DEBUG_KMS("for priv[0x%x]\n", (int)priv);
 
 	if (list_empty(&exynos_drm_ippdrv_list)) {
-		DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
+		DRM_DEBUG_KMS("ippdrv_list is empty.\n");
 		goto err_clear;
 	}
 
@@ -1873,8 +1817,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
 
 		list_for_each_entry_safe(c_node, tc_node,
 			&ippdrv->cmd_list, list) {
-			DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n",
-				__func__, count++, (int)ippdrv);
+			DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
+				count++, (int)ippdrv);
 
 			if (c_node->priv == priv) {
 				/*
@@ -1913,8 +1857,6 @@ static int ipp_probe(struct platform_device *pdev)
 	if (!ctx)
 		return -ENOMEM;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	mutex_init(&ctx->ipp_lock);
 	mutex_init(&ctx->prop_lock);
 
@@ -1978,8 +1920,6 @@ static int ipp_remove(struct platform_device *pdev)
 {
 	struct ipp_context *ctx = platform_get_drvdata(pdev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	/* unregister sub driver */
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
@@ -1999,7 +1939,7 @@ static int ipp_remove(struct platform_device *pdev)
 
 static int ipp_power_ctrl(struct ipp_context *ctx, bool enable)
 {
-	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
+	DRM_DEBUG_KMS("enable[%d]\n", enable);
 
 	return 0;
 }
@@ -2009,8 +1949,6 @@ static int ipp_suspend(struct device *dev)
 {
 	struct ipp_context *ctx = get_ipp_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (pm_runtime_suspended(dev))
 		return 0;
 
@@ -2021,8 +1959,6 @@ static int ipp_resume(struct device *dev)
 {
 	struct ipp_context *ctx = get_ipp_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!pm_runtime_suspended(dev))
 		return ipp_power_ctrl(ctx, true);
 
@@ -2035,8 +1971,6 @@ static int ipp_runtime_suspend(struct device *dev)
 {
 	struct ipp_context *ctx = get_ipp_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	return ipp_power_ctrl(ctx, false);
 }
 
@@ -2044,8 +1978,6 @@ static int ipp_runtime_resume(struct device *dev)
 {
 	struct ipp_context *ctx = get_ipp_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	return ipp_power_ctrl(ctx, true);
 }
 #endif

+ 0 - 16
drivers/gpu/drm/exynos/exynos_drm_plane.c

@@ -81,8 +81,6 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 	int nr;
 	int i;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	nr = exynos_drm_fb_get_buf_cnt(fb);
 	for (i = 0; i < nr; i++) {
 		struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
@@ -159,8 +157,6 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
 	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
 	struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (mode == DRM_MODE_DPMS_ON) {
 		if (exynos_plane->enabled)
 			return;
@@ -189,8 +185,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 {
 	int ret;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
 			crtc_w, crtc_h, src_x >> 16, src_y >> 16,
 			src_w >> 16, src_h >> 16);
@@ -207,8 +201,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 static int exynos_disable_plane(struct drm_plane *plane)
 {
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF);
 
 	return 0;
@@ -218,8 +210,6 @@ static void exynos_plane_destroy(struct drm_plane *plane)
 {
 	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	exynos_disable_plane(plane);
 	drm_plane_cleanup(plane);
 	kfree(exynos_plane);
@@ -233,8 +223,6 @@ static int exynos_plane_set_property(struct drm_plane *plane,
 	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
 	struct exynos_drm_private *dev_priv = dev->dev_private;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (property == dev_priv->plane_zpos_property) {
 		exynos_plane->overlay.zpos = val;
 		return 0;
@@ -256,8 +244,6 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
 	struct exynos_drm_private *dev_priv = dev->dev_private;
 	struct drm_property *prop;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	prop = dev_priv->plane_zpos_property;
 	if (!prop) {
 		prop = drm_property_create_range(dev, 0, "zpos", 0,
@@ -277,8 +263,6 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
 	struct exynos_plane *exynos_plane;
 	int err;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
 	if (!exynos_plane) {
 		DRM_ERROR("failed to allocate plane\n");

+ 18 - 35
drivers/gpu/drm/exynos/exynos_drm_rotator.c

@@ -244,7 +244,7 @@ static int rotator_src_set_size(struct device *dev, int swap,
 	/* Get format */
 	fmt = rotator_reg_get_fmt(rot);
 	if (!rotator_check_reg_fmt(fmt)) {
-		DRM_ERROR("%s:invalid format.\n", __func__);
+		DRM_ERROR("invalid format.\n");
 		return -EINVAL;
 	}
 
@@ -287,7 +287,7 @@ static int rotator_src_set_addr(struct device *dev,
 		/* Get format */
 		fmt = rotator_reg_get_fmt(rot);
 		if (!rotator_check_reg_fmt(fmt)) {
-			DRM_ERROR("%s:invalid format.\n", __func__);
+			DRM_ERROR("invalid format.\n");
 			return -EINVAL;
 		}
 
@@ -381,7 +381,7 @@ static int rotator_dst_set_size(struct device *dev, int swap,
 	/* Get format */
 	fmt = rotator_reg_get_fmt(rot);
 	if (!rotator_check_reg_fmt(fmt)) {
-		DRM_ERROR("%s:invalid format.\n", __func__);
+		DRM_ERROR("invalid format.\n");
 		return -EINVAL;
 	}
 
@@ -422,7 +422,7 @@ static int rotator_dst_set_addr(struct device *dev,
 		/* Get format */
 		fmt = rotator_reg_get_fmt(rot);
 		if (!rotator_check_reg_fmt(fmt)) {
-			DRM_ERROR("%s:invalid format.\n", __func__);
+			DRM_ERROR("invalid format.\n");
 			return -EINVAL;
 		}
 
@@ -471,8 +471,6 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
 {
 	struct drm_exynos_ipp_prop_list *prop_list;
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
 	if (!prop_list) {
 		DRM_ERROR("failed to alloc property list.\n");
@@ -502,7 +500,7 @@ static inline bool rotator_check_drm_fmt(u32 fmt)
 	case DRM_FORMAT_NV12:
 		return true;
 	default:
-		DRM_DEBUG_KMS("%s:not support format\n", __func__);
+		DRM_DEBUG_KMS("not support format\n");
 		return false;
 	}
 }
@@ -516,7 +514,7 @@ static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
 	case EXYNOS_DRM_FLIP_BOTH:
 		return true;
 	default:
-		DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+		DRM_DEBUG_KMS("invalid flip\n");
 		return false;
 	}
 }
@@ -536,19 +534,18 @@ static int rotator_ippdrv_check_property(struct device *dev,
 
 	/* Check format configuration */
 	if (src_config->fmt != dst_config->fmt) {
-		DRM_DEBUG_KMS("%s:not support csc feature\n", __func__);
+		DRM_DEBUG_KMS("not support csc feature\n");
 		return -EINVAL;
 	}
 
 	if (!rotator_check_drm_fmt(dst_config->fmt)) {
-		DRM_DEBUG_KMS("%s:invalid format\n", __func__);
+		DRM_DEBUG_KMS("invalid format\n");
 		return -EINVAL;
 	}
 
 	/* Check transform configuration */
 	if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
-		DRM_DEBUG_KMS("%s:not support source-side rotation\n",
-			__func__);
+		DRM_DEBUG_KMS("not support source-side rotation\n");
 		return -EINVAL;
 	}
 
@@ -561,51 +558,47 @@ static int rotator_ippdrv_check_property(struct device *dev,
 		/* No problem */
 		break;
 	default:
-		DRM_DEBUG_KMS("%s:invalid degree\n", __func__);
+		DRM_DEBUG_KMS("invalid degree\n");
 		return -EINVAL;
 	}
 
 	if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
-		DRM_DEBUG_KMS("%s:not support source-side flip\n", __func__);
+		DRM_DEBUG_KMS("not support source-side flip\n");
 		return -EINVAL;
 	}
 
 	if (!rotator_check_drm_flip(dst_config->flip)) {
-		DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
+		DRM_DEBUG_KMS("invalid flip\n");
 		return -EINVAL;
 	}
 
 	/* Check size configuration */
 	if ((src_pos->x + src_pos->w > src_sz->hsize) ||
 		(src_pos->y + src_pos->h > src_sz->vsize)) {
-		DRM_DEBUG_KMS("%s:out of source buffer bound\n", __func__);
+		DRM_DEBUG_KMS("out of source buffer bound\n");
 		return -EINVAL;
 	}
 
 	if (swap) {
 		if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
 			(dst_pos->y + dst_pos->w > dst_sz->hsize)) {
-			DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
-				__func__);
+			DRM_DEBUG_KMS("out of destination buffer bound\n");
 			return -EINVAL;
 		}
 
 		if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
-			DRM_DEBUG_KMS("%s:not support scale feature\n",
-				__func__);
+			DRM_DEBUG_KMS("not support scale feature\n");
 			return -EINVAL;
 		}
 	} else {
 		if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
 			(dst_pos->y + dst_pos->h > dst_sz->vsize)) {
-			DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
-				__func__);
+			DRM_DEBUG_KMS("out of destination buffer bound\n");
 			return -EINVAL;
 		}
 
 		if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
-			DRM_DEBUG_KMS("%s:not support scale feature\n",
-				__func__);
+			DRM_DEBUG_KMS("not support scale feature\n");
 			return -EINVAL;
 		}
 	}
@@ -693,7 +686,7 @@ static int rotator_probe(struct platform_device *pdev)
 		goto err_ippdrv_register;
 	}
 
-	DRM_DEBUG_KMS("%s:ippdrv[0x%x]\n", __func__, (int)ippdrv);
+	DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv);
 
 	platform_set_drvdata(pdev, rot);
 
@@ -752,8 +745,6 @@ static struct platform_device_id rotator_driver_ids[] = {
 
 static int rotator_clk_crtl(struct rot_context *rot, bool enable)
 {
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (enable) {
 		clk_enable(rot->clock);
 		rot->suspended = false;
@@ -771,8 +762,6 @@ static int rotator_suspend(struct device *dev)
 {
 	struct rot_context *rot = dev_get_drvdata(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (pm_runtime_suspended(dev))
 		return 0;
 
@@ -783,8 +772,6 @@ static int rotator_resume(struct device *dev)
 {
 	struct rot_context *rot = dev_get_drvdata(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	if (!pm_runtime_suspended(dev))
 		return rotator_clk_crtl(rot, true);
 
@@ -797,8 +784,6 @@ static int rotator_runtime_suspend(struct device *dev)
 {
 	struct rot_context *rot = dev_get_drvdata(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	return  rotator_clk_crtl(rot, false);
 }
 
@@ -806,8 +791,6 @@ static int rotator_runtime_resume(struct device *dev)
 {
 	struct rot_context *rot = dev_get_drvdata(dev);
 
-	DRM_DEBUG_KMS("%s\n", __func__);
-
 	return  rotator_clk_crtl(rot, true);
 }
 #endif

+ 6 - 47
drivers/gpu/drm/exynos/exynos_drm_vidi.c

@@ -89,8 +89,6 @@ static bool vidi_display_is_connected(struct device *dev)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * connection request would come from user side
 	 * to do hotplug through specific ioctl.
@@ -105,8 +103,6 @@ static struct edid *vidi_get_edid(struct device *dev,
 	struct edid *edid;
 	int edid_len;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * the edid data comes from user side and it would be set
 	 * to ctx->raw_edid through specific ioctl.
@@ -128,17 +124,13 @@ static struct edid *vidi_get_edid(struct device *dev,
 
 static void *vidi_get_panel(struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO. */
 
 	return NULL;
 }
 
-static int vidi_check_timing(struct device *dev, void *timing)
+static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO. */
 
 	return 0;
@@ -146,8 +138,6 @@ static int vidi_check_timing(struct device *dev, void *timing)
 
 static int vidi_display_power_on(struct device *dev, int mode)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO */
 
 	return 0;
@@ -158,7 +148,7 @@ static struct exynos_drm_display_ops vidi_display_ops = {
 	.is_connected = vidi_display_is_connected,
 	.get_edid = vidi_get_edid,
 	.get_panel = vidi_get_panel,
-	.check_timing = vidi_check_timing,
+	.check_mode = vidi_check_mode,
 	.power_on = vidi_display_power_on,
 };
 
@@ -166,7 +156,7 @@ static void vidi_dpms(struct device *subdrv_dev, int mode)
 {
 	struct vidi_context *ctx = get_vidi_context(subdrv_dev);
 
-	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
+	DRM_DEBUG_KMS("%d\n", mode);
 
 	mutex_lock(&ctx->lock);
 
@@ -196,8 +186,6 @@ static void vidi_apply(struct device *subdrv_dev)
 	struct vidi_win_data *win_data;
 	int i;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
 		if (win_data->enabled && (ovl_ops && ovl_ops->commit))
@@ -212,8 +200,6 @@ static void vidi_commit(struct device *dev)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return;
 }
@@ -222,8 +208,6 @@ static int vidi_enable_vblank(struct device *dev)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return -EPERM;
 
@@ -246,8 +230,6 @@ static void vidi_disable_vblank(struct device *dev)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return;
 
@@ -271,8 +253,6 @@ static void vidi_win_mode_set(struct device *dev,
 	int win;
 	unsigned long offset;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!overlay) {
 		dev_err(dev, "overlay is NULL\n");
 		return;
@@ -282,7 +262,7 @@ static void vidi_win_mode_set(struct device *dev,
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	offset = overlay->fb_x * (overlay->bpp >> 3);
@@ -324,15 +304,13 @@ static void vidi_win_commit(struct device *dev, int zpos)
 	struct vidi_win_data *win_data;
 	int win = zpos;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (ctx->suspended)
 		return;
 
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	win_data = &ctx->win_data[win];
@@ -351,12 +329,10 @@ static void vidi_win_disable(struct device *dev, int zpos)
 	struct vidi_win_data *win_data;
 	int win = zpos;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (win == DEFAULT_ZPOS)
 		win = ctx->default_win;
 
-	if (win < 0 || win > WINDOWS_NR)
+	if (win < 0 || win >= WINDOWS_NR)
 		return;
 
 	win_data = &ctx->win_data[win];
@@ -407,8 +383,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
 
 static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/*
 	 * enable drm irq mode.
 	 * - with irq_enabled = 1, we can use the vblank feature.
@@ -431,8 +405,6 @@ static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 
 static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 {
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	/* TODO. */
 }
 
@@ -441,11 +413,6 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
 	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
 	struct device *dev = subdrv->dev;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	if (enable != false && enable != true)
-		return -EINVAL;
-
 	if (enable) {
 		ctx->suspended = false;
 
@@ -483,8 +450,6 @@ static int vidi_store_connection(struct device *dev,
 	struct vidi_context *ctx = get_vidi_context(dev);
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	ret = kstrtoint(buf, 0, &ctx->connected);
 	if (ret)
 		return ret;
@@ -522,8 +487,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 	struct drm_exynos_vidi_connection *vidi = data;
 	int edid_len;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	if (!vidi) {
 		DRM_DEBUG_KMS("user data for vidi is null.\n");
 		return -EINVAL;
@@ -592,8 +555,6 @@ static int vidi_probe(struct platform_device *pdev)
 	struct exynos_drm_subdrv *subdrv;
 	int ret;
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
@@ -625,8 +586,6 @@ static int vidi_remove(struct platform_device *pdev)
 {
 	struct vidi_context *ctx = platform_get_drvdata(pdev);
 
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
 	if (ctx->raw_edid != (struct edid *)fake_edid_info) {

+ 56 - 75
drivers/gpu/drm/exynos/exynos_hdmi.c

@@ -83,6 +83,7 @@ struct hdmi_resources {
 	struct clk			*sclk_pixel;
 	struct clk			*sclk_hdmiphy;
 	struct clk			*hdmiphy;
+	struct clk			*mout_hdmi;
 	struct regulator_bulk_data	*regul_bulk;
 	int				regul_count;
 };
@@ -689,8 +690,6 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 	u32 mod;
 	u32 vic;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
 	if (hdata->dvi_mode) {
 		hdmi_reg_writeb(hdata, HDMI_VSI_CON,
@@ -755,8 +754,6 @@ static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
 	struct edid *raw_edid;
 	struct hdmi_context *hdata = ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (!hdata->ddc_port)
 		return ERR_PTR(-ENODEV);
 
@@ -777,8 +774,6 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 	const struct hdmiphy_config *confs;
 	int count, i;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (hdata->type == HDMI_TYPE13) {
 		confs = hdmiphy_v13_configs;
 		count = ARRAY_SIZE(hdmiphy_v13_configs);
@@ -796,18 +791,17 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 	return -EINVAL;
 }
 
-static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
+static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
 {
 	struct hdmi_context *hdata = ctx;
 	int ret;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
+		mode->hdisplay, mode->vdisplay, mode->vrefresh,
+		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
+		false, mode->clock * 1000);
 
-	DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
-			timing->yres, timing->refresh,
-			timing->vmode);
-
-	ret = hdmi_find_phy_conf(hdata, timing->pixclock);
+	ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -1042,7 +1036,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
 	}
 }
 
-static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
+static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
 {
 	const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
 	const struct hdmi_v13_core_regs *core =
@@ -1118,9 +1112,9 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
 		hdmi_regs_dump(hdata, "timing apply");
 	}
 
-	clk_disable(hdata->res.sclk_hdmi);
-	clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
-	clk_enable(hdata->res.sclk_hdmi);
+	clk_disable_unprepare(hdata->res.sclk_hdmi);
+	clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
+	clk_prepare_enable(hdata->res.sclk_hdmi);
 
 	/* enable HDMI and timing generator */
 	hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
@@ -1131,7 +1125,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
 		hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
 }
 
-static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
+static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
 {
 	const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
 	const struct hdmi_v14_core_regs *core =
@@ -1285,9 +1279,9 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
 		hdmi_regs_dump(hdata, "timing apply");
 	}
 
-	clk_disable(hdata->res.sclk_hdmi);
-	clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
-	clk_enable(hdata->res.sclk_hdmi);
+	clk_disable_unprepare(hdata->res.sclk_hdmi);
+	clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
+	clk_prepare_enable(hdata->res.sclk_hdmi);
 
 	/* enable HDMI and timing generator */
 	hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
@@ -1298,12 +1292,12 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
 		hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
 }
 
-static void hdmi_timing_apply(struct hdmi_context *hdata)
+static void hdmi_mode_apply(struct hdmi_context *hdata)
 {
 	if (hdata->type == HDMI_TYPE13)
-		hdmi_v13_timing_apply(hdata);
+		hdmi_v13_mode_apply(hdata);
 	else
-		hdmi_v14_timing_apply(hdata);
+		hdmi_v14_mode_apply(hdata);
 }
 
 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
@@ -1311,9 +1305,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 	u8 buffer[2];
 	u32 reg;
 
-	clk_disable(hdata->res.sclk_hdmi);
-	clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
-	clk_enable(hdata->res.sclk_hdmi);
+	clk_disable_unprepare(hdata->res.sclk_hdmi);
+	clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
+	clk_prepare_enable(hdata->res.sclk_hdmi);
 
 	/* operation mode */
 	buffer[0] = 0x1f;
@@ -1336,8 +1330,6 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 
 static void hdmiphy_poweron(struct hdmi_context *hdata)
 {
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (hdata->type == HDMI_TYPE14)
 		hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
 			HDMI_PHY_POWER_OFF_EN);
@@ -1345,8 +1337,6 @@ static void hdmiphy_poweron(struct hdmi_context *hdata)
 
 static void hdmiphy_poweroff(struct hdmi_context *hdata)
 {
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (hdata->type == HDMI_TYPE14)
 		hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
 			HDMI_PHY_POWER_OFF_EN);
@@ -1410,8 +1400,6 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
 
 static void hdmi_conf_apply(struct hdmi_context *hdata)
 {
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	hdmiphy_conf_reset(hdata);
 	hdmiphy_conf_apply(hdata);
 
@@ -1423,7 +1411,7 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
 	hdmi_audio_init(hdata);
 
 	/* setting core registers */
-	hdmi_timing_apply(hdata);
+	hdmi_mode_apply(hdata);
 	hdmi_audio_control(hdata, true);
 
 	hdmi_regs_dump(hdata, "start");
@@ -1569,8 +1557,7 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
 			(m->vsync_start - m->vdisplay) / 2);
 		hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
 		hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
-		hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
-			((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
+		hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
 		hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
 		hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
 		hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
@@ -1580,7 +1567,10 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
 			(m->htotal / 2) + (m->hsync_start - m->hdisplay));
 		hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
 		hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
-		hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
+		hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
+		hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
+		hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
+		hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
 		hdmi_set_reg(tg->vact_st3, 2, 0x0);
 		hdmi_set_reg(tg->vact_st4, 2, 0x0);
 	} else {
@@ -1602,6 +1592,9 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
 		hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
 		hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
 		hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
+		hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
+		hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
+		hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
 	}
 
 	/* Following values & calculations are same irrespective of mode type */
@@ -1633,22 +1626,19 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
 	hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
 	hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
 	hdmi_set_reg(tg->vsync, 2, 0x1);
-	hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
 	hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
 	hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
-	hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
 	hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
-	hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
 	hdmi_set_reg(tg->tg_3d, 1, 0x0);
 }
 
-static void hdmi_mode_set(void *ctx, void *mode)
+static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
 {
 	struct hdmi_context *hdata = ctx;
 	struct drm_display_mode *m = mode;
 
-	DRM_DEBUG_KMS("[%s]: xres=%d, yres=%d, refresh=%d, intl=%s\n",
-		__func__, m->hdisplay, m->vdisplay,
+	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
+		m->hdisplay, m->vdisplay,
 		m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
 		"INTERLACED" : "PROGERESSIVE");
 
@@ -1661,8 +1651,6 @@ static void hdmi_mode_set(void *ctx, void *mode)
 static void hdmi_get_max_resol(void *ctx, unsigned int *width,
 					unsigned int *height)
 {
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	*width = MAX_WIDTH;
 	*height = MAX_HEIGHT;
 }
@@ -1671,8 +1659,6 @@ static void hdmi_commit(void *ctx)
 {
 	struct hdmi_context *hdata = ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mutex_lock(&hdata->hdmi_mutex);
 	if (!hdata->powered) {
 		mutex_unlock(&hdata->hdmi_mutex);
@@ -1687,8 +1673,6 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 {
 	struct hdmi_resources *res = &hdata->res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mutex_lock(&hdata->hdmi_mutex);
 	if (hdata->powered) {
 		mutex_unlock(&hdata->hdmi_mutex);
@@ -1699,10 +1683,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 
 	mutex_unlock(&hdata->hdmi_mutex);
 
-	regulator_bulk_enable(res->regul_count, res->regul_bulk);
-	clk_enable(res->hdmiphy);
-	clk_enable(res->hdmi);
-	clk_enable(res->sclk_hdmi);
+	if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
+		DRM_DEBUG_KMS("failed to enable regulator bulk\n");
+
+	clk_prepare_enable(res->hdmiphy);
+	clk_prepare_enable(res->hdmi);
+	clk_prepare_enable(res->sclk_hdmi);
 
 	hdmiphy_poweron(hdata);
 }
@@ -1711,8 +1697,6 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
 {
 	struct hdmi_resources *res = &hdata->res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mutex_lock(&hdata->hdmi_mutex);
 	if (!hdata->powered)
 		goto out;
@@ -1725,9 +1709,9 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
 	hdmiphy_conf_reset(hdata);
 	hdmiphy_poweroff(hdata);
 
-	clk_disable(res->sclk_hdmi);
-	clk_disable(res->hdmi);
-	clk_disable(res->hdmiphy);
+	clk_disable_unprepare(res->sclk_hdmi);
+	clk_disable_unprepare(res->hdmi);
+	clk_disable_unprepare(res->hdmiphy);
 	regulator_bulk_disable(res->regul_count, res->regul_bulk);
 
 	mutex_lock(&hdata->hdmi_mutex);
@@ -1742,7 +1726,7 @@ static void hdmi_dpms(void *ctx, int mode)
 {
 	struct hdmi_context *hdata = ctx;
 
-	DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
+	DRM_DEBUG_KMS("mode %d\n", mode);
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
@@ -1765,7 +1749,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
 	/* display */
 	.is_connected	= hdmi_is_connected,
 	.get_edid	= hdmi_get_edid,
-	.check_timing	= hdmi_check_timing,
+	.check_mode	= hdmi_check_mode,
 
 	/* manager */
 	.mode_set	= hdmi_mode_set,
@@ -1831,8 +1815,13 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
 		DRM_ERROR("failed to get clock 'hdmiphy'\n");
 		goto fail;
 	}
+	res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
+	if (IS_ERR(res->mout_hdmi)) {
+		DRM_ERROR("failed to get clock 'mout_hdmi'\n");
+		goto fail;
+	}
 
-	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+	clk_set_parent(res->mout_hdmi, res->sclk_pixel);
 
 	res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
 		sizeof(res->regul_bulk[0]), GFP_KERNEL);
@@ -1877,7 +1866,6 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
 {
 	struct device_node *np = dev->of_node;
 	struct s5p_hdmi_platform_data *pd;
-	enum of_gpio_flags flags;
 	u32 value;
 
 	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
@@ -1891,7 +1879,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
 		goto err_data;
 	}
 
-	pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
+	pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
 
 	return pd;
 
@@ -1929,6 +1917,9 @@ static struct of_device_id hdmi_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-hdmi",
 		.data	= (void	*)HDMI_TYPE14,
+	}, {
+		.compatible = "samsung,exynos4212-hdmi",
+		.data	= (void	*)HDMI_TYPE14,
 	}, {
 		/* end node */
 	}
@@ -1944,8 +1935,6 @@ static int hdmi_probe(struct platform_device *pdev)
 	struct resource *res;
 	int ret;
 
-	DRM_DEBUG_KMS("[%d]\n", __LINE__);
-
 	if (dev->of_node) {
 		pdata = drm_hdmi_dt_parse_pdata(dev);
 		if (IS_ERR(pdata)) {
@@ -2071,8 +2060,6 @@ static int hdmi_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	pm_runtime_disable(dev);
 
 	/* hdmiphy i2c driver */
@@ -2089,8 +2076,6 @@ static int hdmi_suspend(struct device *dev)
 	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
 	struct hdmi_context *hdata = ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	disable_irq(hdata->irq);
 
 	hdata->hpd = false;
@@ -2098,7 +2083,7 @@ static int hdmi_suspend(struct device *dev)
 		drm_helper_hpd_irq_event(ctx->drm_dev);
 
 	if (pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
+		DRM_DEBUG_KMS("Already suspended\n");
 		return 0;
 	}
 
@@ -2112,14 +2097,12 @@ static int hdmi_resume(struct device *dev)
 	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
 	struct hdmi_context *hdata = ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
 	enable_irq(hdata->irq);
 
 	if (!pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
+		DRM_DEBUG_KMS("Already resumed\n");
 		return 0;
 	}
 
@@ -2134,7 +2117,6 @@ static int hdmi_runtime_suspend(struct device *dev)
 {
 	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
 	struct hdmi_context *hdata = ctx->ctx;
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
 	hdmi_poweroff(hdata);
 
@@ -2145,7 +2127,6 @@ static int hdmi_runtime_resume(struct device *dev)
 {
 	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
 	struct hdmi_context *hdata = ctx->ctx;
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
 	hdmi_poweron(hdata);
 

+ 4 - 0
drivers/gpu/drm/exynos/exynos_hdmiphy.c

@@ -50,6 +50,10 @@ static const struct i2c_device_id hdmiphy_id[] = {
 static struct of_device_id hdmiphy_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-hdmiphy",
+	}, {
+		.compatible = "samsung,exynos4210-hdmiphy",
+	}, {
+		.compatible = "samsung,exynos4212-hdmiphy",
 	}, {
 		/* end node */
 	}

+ 65 - 59
drivers/gpu/drm/exynos/exynos_mixer.c

@@ -78,6 +78,7 @@ struct mixer_resources {
 enum mixer_version_id {
 	MXR_VER_0_0_0_16,
 	MXR_VER_16_0_33_0,
+	MXR_VER_128_0_0_184,
 };
 
 struct mixer_context {
@@ -283,17 +284,19 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
 	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
 				MXR_CFG_SCAN_PROGRASSIVE);
 
-	/* choosing between porper HD and SD mode */
-	if (height <= 480)
-		val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
-	else if (height <= 576)
-		val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
-	else if (height <= 720)
-		val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
-	else if (height <= 1080)
-		val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
-	else
-		val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
+	if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
+		/* choosing between proper HD and SD mode */
+		if (height <= 480)
+			val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
+		else if (height <= 576)
+			val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
+		else if (height <= 720)
+			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
+		else if (height <= 1080)
+			val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
+		else
+			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
+	}
 
 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 }
@@ -376,7 +379,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 	unsigned long flags;
 	struct hdmi_win_data *win_data;
 	unsigned int x_ratio, y_ratio;
-	unsigned int buf_num;
+	unsigned int buf_num = 1;
 	dma_addr_t luma_addr[2], chroma_addr[2];
 	bool tiled_mode = false;
 	bool crcb_mode = false;
@@ -557,6 +560,14 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 	/* setup geometry */
 	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
 
+	/* setup display size */
+	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
+		win == MIXER_DEFAULT_WIN) {
+		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
+		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
+		mixer_reg_write(res, MXR_RESOLUTION, val);
+	}
+
 	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
 	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
 	val |= MXR_GRP_WH_H_SCALE(x_ratio);
@@ -581,7 +592,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 	mixer_cfg_layer(ctx, win, true);
 
 	/* layer update mandatory for mixer 16.0.33.0 */
-	if (ctx->mxr_ver == MXR_VER_16_0_33_0)
+	if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
+		ctx->mxr_ver == MXR_VER_128_0_0_184)
 		mixer_layer_update(ctx);
 
 	mixer_run(ctx);
@@ -696,8 +708,6 @@ static int mixer_enable_vblank(void *ctx, int pipe)
 	struct mixer_context *mixer_ctx = ctx;
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mixer_ctx->pipe = pipe;
 
 	/* enable vsync interrupt */
@@ -712,8 +722,6 @@ static void mixer_disable_vblank(void *ctx)
 	struct mixer_context *mixer_ctx = ctx;
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	/* disable vsync interrupt */
 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
@@ -725,8 +733,6 @@ static void mixer_win_mode_set(void *ctx,
 	struct hdmi_win_data *win_data;
 	int win;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (!overlay) {
 		DRM_ERROR("overlay is NULL\n");
 		return;
@@ -742,7 +748,7 @@ static void mixer_win_mode_set(void *ctx,
 	if (win == DEFAULT_ZPOS)
 		win = MIXER_DEFAULT_WIN;
 
-	if (win < 0 || win > MIXER_WIN_NR) {
+	if (win < 0 || win >= MIXER_WIN_NR) {
 		DRM_ERROR("mixer window[%d] is wrong\n", win);
 		return;
 	}
@@ -776,7 +782,7 @@ static void mixer_win_commit(void *ctx, int win)
 {
 	struct mixer_context *mixer_ctx = ctx;
 
-	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
+	DRM_DEBUG_KMS("win: %d\n", win);
 
 	mutex_lock(&mixer_ctx->mixer_mutex);
 	if (!mixer_ctx->powered) {
@@ -799,7 +805,7 @@ static void mixer_win_disable(void *ctx, int win)
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 	unsigned long flags;
 
-	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
+	DRM_DEBUG_KMS("win: %d\n", win);
 
 	mutex_lock(&mixer_ctx->mixer_mutex);
 	if (!mixer_ctx->powered) {
@@ -820,17 +826,21 @@ static void mixer_win_disable(void *ctx, int win)
 	mixer_ctx->win_data[win].enabled = false;
 }
 
-static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
+static int mixer_check_mode(void *ctx, struct drm_display_mode *mode)
 {
+	struct mixer_context *mixer_ctx = ctx;
 	u32 w, h;
 
-	w = timing->xres;
-	h = timing->yres;
+	w = mode->hdisplay;
+	h = mode->vdisplay;
 
-	DRM_DEBUG_KMS("%s : xres=%d, yres=%d, refresh=%d, intl=%d\n",
-		__func__, timing->xres, timing->yres,
-		timing->refresh, (timing->vmode &
-		FB_VMODE_INTERLACED) ? true : false);
+	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
+		mode->hdisplay, mode->vdisplay, mode->vrefresh,
+		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
+
+	if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16 ||
+		mixer_ctx->mxr_ver == MXR_VER_128_0_0_184)
+		return 0;
 
 	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
 		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
@@ -891,8 +901,6 @@ static void mixer_poweron(struct mixer_context *ctx)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mutex_lock(&ctx->mixer_mutex);
 	if (ctx->powered) {
 		mutex_unlock(&ctx->mixer_mutex);
@@ -901,10 +909,10 @@ static void mixer_poweron(struct mixer_context *ctx)
 	ctx->powered = true;
 	mutex_unlock(&ctx->mixer_mutex);
 
-	clk_enable(res->mixer);
+	clk_prepare_enable(res->mixer);
 	if (ctx->vp_enabled) {
-		clk_enable(res->vp);
-		clk_enable(res->sclk_mixer);
+		clk_prepare_enable(res->vp);
+		clk_prepare_enable(res->sclk_mixer);
 	}
 
 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
@@ -917,8 +925,6 @@ static void mixer_poweroff(struct mixer_context *ctx)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mutex_lock(&ctx->mixer_mutex);
 	if (!ctx->powered)
 		goto out;
@@ -928,10 +934,10 @@ static void mixer_poweroff(struct mixer_context *ctx)
 
 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
 
-	clk_disable(res->mixer);
+	clk_disable_unprepare(res->mixer);
 	if (ctx->vp_enabled) {
-		clk_disable(res->vp);
-		clk_disable(res->sclk_mixer);
+		clk_disable_unprepare(res->vp);
+		clk_disable_unprepare(res->sclk_mixer);
 	}
 
 	mutex_lock(&ctx->mixer_mutex);
@@ -945,8 +951,6 @@ static void mixer_dpms(void *ctx, int mode)
 {
 	struct mixer_context *mixer_ctx = ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		if (pm_runtime_suspended(mixer_ctx->dev))
@@ -978,7 +982,7 @@ static struct exynos_mixer_ops mixer_ops = {
 	.win_disable		= mixer_win_disable,
 
 	/* display */
-	.check_timing		= mixer_check_timing,
+	.check_mode		= mixer_check_mode,
 };
 
 static irqreturn_t mixer_irq_handler(int irq, void *arg)
@@ -1128,12 +1132,17 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
 	return 0;
 }
 
-static struct mixer_drv_data exynos5_mxr_drv_data = {
+static struct mixer_drv_data exynos5420_mxr_drv_data = {
+	.version = MXR_VER_128_0_0_184,
+	.is_vp_enabled = 0,
+};
+
+static struct mixer_drv_data exynos5250_mxr_drv_data = {
 	.version = MXR_VER_16_0_33_0,
 	.is_vp_enabled = 0,
 };
 
-static struct mixer_drv_data exynos4_mxr_drv_data = {
+static struct mixer_drv_data exynos4210_mxr_drv_data = {
 	.version = MXR_VER_0_0_0_16,
 	.is_vp_enabled = 1,
 };
@@ -1141,10 +1150,10 @@ static struct mixer_drv_data exynos4_mxr_drv_data = {
 static struct platform_device_id mixer_driver_types[] = {
 	{
 		.name		= "s5p-mixer",
-		.driver_data	= (unsigned long)&exynos4_mxr_drv_data,
+		.driver_data	= (unsigned long)&exynos4210_mxr_drv_data,
 	}, {
 		.name		= "exynos5-mixer",
-		.driver_data	= (unsigned long)&exynos5_mxr_drv_data,
+		.driver_data	= (unsigned long)&exynos5250_mxr_drv_data,
 	}, {
 		/* end node */
 	}
@@ -1153,7 +1162,13 @@ static struct platform_device_id mixer_driver_types[] = {
 static struct of_device_id mixer_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-mixer",
-		.data	= &exynos5_mxr_drv_data,
+		.data	= &exynos5250_mxr_drv_data,
+	}, {
+		.compatible = "samsung,exynos5250-mixer",
+		.data	= &exynos5250_mxr_drv_data,
+	}, {
+		.compatible = "samsung,exynos5420-mixer",
+		.data	= &exynos5420_mxr_drv_data,
 	}, {
 		/* end node */
 	}
@@ -1186,8 +1201,7 @@ static int mixer_probe(struct platform_device *pdev)
 
 	if (dev->of_node) {
 		const struct of_device_id *match;
-		match = of_match_node(of_match_ptr(mixer_match_types),
-							  dev->of_node);
+		match = of_match_node(mixer_match_types, dev->of_node);
 		drv = (struct mixer_drv_data *)match->data;
 	} else {
 		drv = (struct mixer_drv_data *)
@@ -1251,10 +1265,8 @@ static int mixer_suspend(struct device *dev)
 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
+		DRM_DEBUG_KMS("Already suspended\n");
 		return 0;
 	}
 
@@ -1268,10 +1280,8 @@ static int mixer_resume(struct device *dev)
 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	if (!pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
+		DRM_DEBUG_KMS("Already resumed\n");
 		return 0;
 	}
 
@@ -1287,8 +1297,6 @@ static int mixer_runtime_suspend(struct device *dev)
 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mixer_poweroff(ctx);
 
 	return 0;
@@ -1299,8 +1307,6 @@ static int mixer_runtime_resume(struct device *dev)
 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
 
-	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
 	mixer_poweron(ctx);
 
 	return 0;

+ 7 - 0
drivers/gpu/drm/exynos/regs-mixer.h

@@ -44,6 +44,9 @@
 #define MXR_CM_COEFF_Y			0x0080
 #define MXR_CM_COEFF_CB			0x0084
 #define MXR_CM_COEFF_CR			0x0088
+#define MXR_MO				0x0304
+#define MXR_RESOLUTION			0x0310
+
 #define MXR_GRAPHIC0_BASE_S		0x2024
 #define MXR_GRAPHIC1_BASE_S		0x2044
 
@@ -119,6 +122,10 @@
 #define MXR_GRP_WH_WIDTH(x)		MXR_MASK_VAL(x, 26, 16)
 #define MXR_GRP_WH_HEIGHT(x)		MXR_MASK_VAL(x, 10, 0)
 
+/* bits for MXR_RESOLUTION */
+#define MXR_MXR_RES_HEIGHT(x)		MXR_MASK_VAL(x, 26, 16)
+#define MXR_MXR_RES_WIDTH(x)		MXR_MASK_VAL(x, 10, 0)
+
 /* bits for MXR_GRAPHICn_SXY */
 #define MXR_GRP_SXY_SX(x)		MXR_MASK_VAL(x, 26, 16)
 #define MXR_GRP_SXY_SY(x)		MXR_MASK_VAL(x, 10, 0)

+ 1 - 0
drivers/gpu/drm/i915/Makefile

@@ -36,6 +36,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  intel_overlay.o \
 	  intel_sprite.o \
 	  intel_opregion.o \
+	  intel_sideband.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
 	  dvo_ivch.o \

+ 26 - 2
drivers/gpu/drm/i915/dvo_ch7xxx.c

@@ -32,12 +32,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define CH7xxx_REG_DID		0x4b
 
 #define CH7011_VID		0x83 /* 7010 as well */
+#define CH7010B_VID		0x05
 #define CH7009A_VID		0x84
 #define CH7009B_VID		0x85
 #define CH7301_VID		0x95
 
 #define CH7xxx_VID		0x84
 #define CH7xxx_DID		0x17
+#define CH7010_DID		0x16
 
 #define CH7xxx_NUM_REGS		0x4c
 
@@ -87,11 +89,20 @@ static struct ch7xxx_id_struct {
 	char *name;
 } ch7xxx_ids[] = {
 	{ CH7011_VID, "CH7011" },
+	{ CH7010B_VID, "CH7010B" },
 	{ CH7009A_VID, "CH7009A" },
 	{ CH7009B_VID, "CH7009B" },
 	{ CH7301_VID, "CH7301" },
 };
 
+static struct ch7xxx_did_struct {
+	uint8_t did;
+	char *name;
+} ch7xxx_dids[] = {
+	{ CH7xxx_DID, "CH7XXX" },
+	{ CH7010_DID, "CH7010B" },
+};
+
 struct ch7xxx_priv {
 	bool quiet;
 };
@@ -108,6 +119,18 @@ static char *ch7xxx_get_id(uint8_t vid)
 	return NULL;
 }
 
+static char *ch7xxx_get_did(uint8_t did)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ch7xxx_dids); i++) {
+		if (ch7xxx_dids[i].did == did)
+			return ch7xxx_dids[i].name;
+	}
+
+	return NULL;
+}
+
 /** Reads an 8 bit register */
 static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
@@ -179,7 +202,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
 	/* this will detect the CH7xxx chip on the specified i2c bus */
 	struct ch7xxx_priv *ch7xxx;
 	uint8_t vendor, device;
-	char *name;
+	char *name, *devid;
 
 	ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL);
 	if (ch7xxx == NULL)
@@ -204,7 +227,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
 	if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device))
 		goto out;
 
-	if (device != CH7xxx_DID) {
+	devid = ch7xxx_get_did(device);
+	if (!devid) {
 		DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
 				"slave %d.\n",
 			  vendor, adapter->name, dvo->slave_addr);

+ 376 - 97
drivers/gpu/drm/i915/i915_debugfs.c

@@ -61,11 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data)
 
 	seq_printf(m, "gen: %d\n", info->gen);
 	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
-#define DEV_INFO_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
-#define DEV_INFO_SEP ;
-	DEV_INFO_FLAGS;
-#undef DEV_INFO_FLAG
-#undef DEV_INFO_SEP
+#define PRINT_FLAG(x)  seq_printf(m, #x ": %s\n", yesno(info->x))
+#define SEP_SEMICOLON ;
+	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
+#undef PRINT_FLAG
+#undef SEP_SEMICOLON
 
 	return 0;
 }
@@ -196,6 +196,32 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 	} \
 } while (0)
 
+struct file_stats {
+	int count;
+	size_t total, active, inactive, unbound;
+};
+
+static int per_file_stats(int id, void *ptr, void *data)
+{
+	struct drm_i915_gem_object *obj = ptr;
+	struct file_stats *stats = data;
+
+	stats->count++;
+	stats->total += obj->base.size;
+
+	if (obj->gtt_space) {
+		if (!list_empty(&obj->ring_list))
+			stats->active += obj->base.size;
+		else
+			stats->inactive += obj->base.size;
+	} else {
+		if (!list_empty(&obj->global_list))
+			stats->unbound += obj->base.size;
+	}
+
+	return 0;
+}
+
 static int i915_gem_object_info(struct seq_file *m, void* data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -204,6 +230,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	u32 count, mappable_count, purgeable_count;
 	size_t size, mappable_size, purgeable_size;
 	struct drm_i915_gem_object *obj;
+	struct drm_file *file;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -215,7 +242,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   dev_priv->mm.object_memory);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_objects(&dev_priv->mm.bound_list, gtt_list);
+	count_objects(&dev_priv->mm.bound_list, global_list);
 	seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n",
 		   count, mappable_count, size, mappable_size);
 
@@ -230,7 +257,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   count, mappable_count, size, mappable_size);
 
 	size = count = purgeable_size = purgeable_count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
 		size += obj->base.size, ++count;
 		if (obj->madv == I915_MADV_DONTNEED)
 			purgeable_size += obj->base.size, ++purgeable_count;
@@ -238,7 +265,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	seq_printf(m, "%u unbound objects, %zu bytes\n", count, size);
 
 	size = count = mappable_size = mappable_count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		if (obj->fault_mappable) {
 			size += obj->gtt_space->size;
 			++count;
@@ -263,6 +290,21 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   dev_priv->gtt.total,
 		   dev_priv->gtt.mappable_end - dev_priv->gtt.start);
 
+	seq_printf(m, "\n");
+	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
+		struct file_stats stats;
+
+		memset(&stats, 0, sizeof(stats));
+		idr_for_each(&file->object_idr, per_file_stats, &stats);
+		seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n",
+			   get_pid_task(file->pid, PIDTYPE_PID)->comm,
+			   stats.count,
+			   stats.total,
+			   stats.active,
+			   stats.inactive,
+			   stats.unbound);
+	}
+
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -283,7 +325,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
 		return ret;
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		if (list == PINNED_LIST && obj->pin_count == 0)
 			continue;
 
@@ -570,6 +612,7 @@ static const char *ring_str(int ring)
 	case RCS: return "render";
 	case VCS: return "bsd";
 	case BCS: return "blt";
+	case VECS: return "vebox";
 	default: return "";
 	}
 }
@@ -604,73 +647,187 @@ static const char *purgeable_flag(int purgeable)
 	return purgeable ? " purgeable" : "";
 }
 
-static void print_error_buffers(struct seq_file *m,
+static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
+{
+
+	if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
+		e->err = -ENOSPC;
+		return false;
+	}
+
+	if (e->bytes == e->size - 1 || e->err)
+		return false;
+
+	return true;
+}
+
+static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
+			      unsigned len)
+{
+	if (e->pos + len <= e->start) {
+		e->pos += len;
+		return false;
+	}
+
+	/* First vsnprintf needs to fit in its entirety for memmove */
+	if (len >= e->size) {
+		e->err = -EIO;
+		return false;
+	}
+
+	return true;
+}
+
+static void __i915_error_advance(struct drm_i915_error_state_buf *e,
+				 unsigned len)
+{
+	/* If this is first printf in this window, adjust it so that
+	 * start position matches start of the buffer
+	 */
+
+	if (e->pos < e->start) {
+		const size_t off = e->start - e->pos;
+
+		/* Should not happen but be paranoid */
+		if (off > len || e->bytes) {
+			e->err = -EIO;
+			return;
+		}
+
+		memmove(e->buf, e->buf + off, len - off);
+		e->bytes = len - off;
+		e->pos = e->start;
+		return;
+	}
+
+	e->bytes += len;
+	e->pos += len;
+}
+
+static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
+			       const char *f, va_list args)
+{
+	unsigned len;
+
+	if (!__i915_error_ok(e))
+		return;
+
+	/* Seek the first printf which is hits start position */
+	if (e->pos < e->start) {
+		len = vsnprintf(NULL, 0, f, args);
+		if (!__i915_error_seek(e, len))
+			return;
+	}
+
+	len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
+	if (len >= e->size - e->bytes)
+		len = e->size - e->bytes - 1;
+
+	__i915_error_advance(e, len);
+}
+
+static void i915_error_puts(struct drm_i915_error_state_buf *e,
+			    const char *str)
+{
+	unsigned len;
+
+	if (!__i915_error_ok(e))
+		return;
+
+	len = strlen(str);
+
+	/* Seek the first printf which is hits start position */
+	if (e->pos < e->start) {
+		if (!__i915_error_seek(e, len))
+			return;
+	}
+
+	if (len >= e->size - e->bytes)
+		len = e->size - e->bytes - 1;
+	memcpy(e->buf + e->bytes, str, len);
+
+	__i915_error_advance(e, len);
+}
+
+void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
+{
+	va_list args;
+
+	va_start(args, f);
+	i915_error_vprintf(e, f, args);
+	va_end(args);
+}
+
+#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
+#define err_puts(e, s) i915_error_puts(e, s)
+
+static void print_error_buffers(struct drm_i915_error_state_buf *m,
 				const char *name,
 				struct drm_i915_error_buffer *err,
 				int count)
 {
-	seq_printf(m, "%s [%d]:\n", name, count);
+	err_printf(m, "%s [%d]:\n", name, count);
 
 	while (count--) {
-		seq_printf(m, "  %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",
+		err_printf(m, "  %08x %8u %02x %02x %x %x",
 			   err->gtt_offset,
 			   err->size,
 			   err->read_domains,
 			   err->write_domain,
-			   err->rseqno, err->wseqno,
-			   pin_flag(err->pinned),
-			   tiling_flag(err->tiling),
-			   dirty_flag(err->dirty),
-			   purgeable_flag(err->purgeable),
-			   err->ring != -1 ? " " : "",
-			   ring_str(err->ring),
-			   cache_level_str(err->cache_level));
+			   err->rseqno, err->wseqno);
+		err_puts(m, pin_flag(err->pinned));
+		err_puts(m, tiling_flag(err->tiling));
+		err_puts(m, dirty_flag(err->dirty));
+		err_puts(m, purgeable_flag(err->purgeable));
+		err_puts(m, err->ring != -1 ? " " : "");
+		err_puts(m, ring_str(err->ring));
+		err_puts(m, cache_level_str(err->cache_level));
 
 		if (err->name)
-			seq_printf(m, " (name: %d)", err->name);
+			err_printf(m, " (name: %d)", err->name);
 		if (err->fence_reg != I915_FENCE_REG_NONE)
-			seq_printf(m, " (fence: %d)", err->fence_reg);
+			err_printf(m, " (fence: %d)", err->fence_reg);
 
-		seq_printf(m, "\n");
+		err_puts(m, "\n");
 		err++;
 	}
 }
 
-static void i915_ring_error_state(struct seq_file *m,
+static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
 				  struct drm_device *dev,
 				  struct drm_i915_error_state *error,
 				  unsigned ring)
 {
 	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
-	seq_printf(m, "%s command stream:\n", ring_str(ring));
-	seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
-	seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
-	seq_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
-	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
-	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
-	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
-	seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
+	err_printf(m, "%s command stream:\n", ring_str(ring));
+	err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
+	err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
+	err_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
+	err_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
+	err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
+	err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
+	err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
 	if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
-		seq_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
+		err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
 
 	if (INTEL_INFO(dev)->gen >= 4)
-		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
-	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
-	seq_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
+		err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+	err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
+	err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
 	if (INTEL_INFO(dev)->gen >= 6) {
-		seq_printf(m, "  RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
-		seq_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
-		seq_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
+		err_printf(m, "  RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
+		err_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
+		err_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
 			   error->semaphore_mboxes[ring][0],
 			   error->semaphore_seqno[ring][0]);
-		seq_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
+		err_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
 			   error->semaphore_mboxes[ring][1],
 			   error->semaphore_seqno[ring][1]);
 	}
-	seq_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
-	seq_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
-	seq_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
-	seq_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
+	err_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
+	err_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
+	err_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
+	err_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
 }
 
 struct i915_error_state_file_priv {
@@ -678,9 +835,11 @@ struct i915_error_state_file_priv {
 	struct drm_i915_error_state *error;
 };
 
-static int i915_error_state(struct seq_file *m, void *unused)
+
+static int i915_error_state(struct i915_error_state_file_priv *error_priv,
+			    struct drm_i915_error_state_buf *m)
+
 {
-	struct i915_error_state_file_priv *error_priv = m->private;
 	struct drm_device *dev = error_priv->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error = error_priv->error;
@@ -688,34 +847,35 @@ static int i915_error_state(struct seq_file *m, void *unused)
 	int i, j, page, offset, elt;
 
 	if (!error) {
-		seq_printf(m, "no error state collected\n");
+		err_printf(m, "no error state collected\n");
 		return 0;
 	}
 
-	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
+	err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
 		   error->time.tv_usec);
-	seq_printf(m, "Kernel: " UTS_RELEASE "\n");
-	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
-	seq_printf(m, "EIR: 0x%08x\n", error->eir);
-	seq_printf(m, "IER: 0x%08x\n", error->ier);
-	seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
-	seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
-	seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
-	seq_printf(m, "CCID: 0x%08x\n", error->ccid);
+	err_printf(m, "Kernel: " UTS_RELEASE "\n");
+	err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
+	err_printf(m, "EIR: 0x%08x\n", error->eir);
+	err_printf(m, "IER: 0x%08x\n", error->ier);
+	err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+	err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
+	err_printf(m, "CCID: 0x%08x\n", error->ccid);
 
 	for (i = 0; i < dev_priv->num_fence_regs; i++)
-		seq_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
+		err_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
 
 	for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
-		seq_printf(m, "  INSTDONE_%d: 0x%08x\n", i, error->extra_instdone[i]);
+		err_printf(m, "  INSTDONE_%d: 0x%08x\n", i,
+			   error->extra_instdone[i]);
 
 	if (INTEL_INFO(dev)->gen >= 6) {
-		seq_printf(m, "ERROR: 0x%08x\n", error->error);
-		seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
+		err_printf(m, "ERROR: 0x%08x\n", error->error);
+		err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
 	}
 
 	if (INTEL_INFO(dev)->gen == 7)
-		seq_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
 	for_each_ring(ring, dev_priv, i)
 		i915_ring_error_state(m, dev, error, i);
@@ -734,24 +894,25 @@ static int i915_error_state(struct seq_file *m, void *unused)
 		struct drm_i915_error_object *obj;
 
 		if ((obj = error->ring[i].batchbuffer)) {
-			seq_printf(m, "%s --- gtt_offset = 0x%08x\n",
+			err_printf(m, "%s --- gtt_offset = 0x%08x\n",
 				   dev_priv->ring[i].name,
 				   obj->gtt_offset);
 			offset = 0;
 			for (page = 0; page < obj->page_count; page++) {
 				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-					seq_printf(m, "%08x :  %08x\n", offset, obj->pages[page][elt]);
+					err_printf(m, "%08x :  %08x\n", offset,
+						   obj->pages[page][elt]);
 					offset += 4;
 				}
 			}
 		}
 
 		if (error->ring[i].num_requests) {
-			seq_printf(m, "%s --- %d requests\n",
+			err_printf(m, "%s --- %d requests\n",
 				   dev_priv->ring[i].name,
 				   error->ring[i].num_requests);
 			for (j = 0; j < error->ring[i].num_requests; j++) {
-				seq_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
+				err_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
 					   error->ring[i].requests[j].seqno,
 					   error->ring[i].requests[j].jiffies,
 					   error->ring[i].requests[j].tail);
@@ -759,13 +920,13 @@ static int i915_error_state(struct seq_file *m, void *unused)
 		}
 
 		if ((obj = error->ring[i].ringbuffer)) {
-			seq_printf(m, "%s --- ringbuffer = 0x%08x\n",
+			err_printf(m, "%s --- ringbuffer = 0x%08x\n",
 				   dev_priv->ring[i].name,
 				   obj->gtt_offset);
 			offset = 0;
 			for (page = 0; page < obj->page_count; page++) {
 				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-					seq_printf(m, "%08x :  %08x\n",
+					err_printf(m, "%08x :  %08x\n",
 						   offset,
 						   obj->pages[page][elt]);
 					offset += 4;
@@ -775,12 +936,12 @@ static int i915_error_state(struct seq_file *m, void *unused)
 
 		obj = error->ring[i].ctx;
 		if (obj) {
-			seq_printf(m, "%s --- HW Context = 0x%08x\n",
+			err_printf(m, "%s --- HW Context = 0x%08x\n",
 				   dev_priv->ring[i].name,
 				   obj->gtt_offset);
 			offset = 0;
 			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
-				seq_printf(m, "[%04x] %08x %08x %08x %08x\n",
+				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
 					   offset,
 					   obj->pages[0][elt],
 					   obj->pages[0][elt+1],
@@ -806,8 +967,7 @@ i915_error_state_write(struct file *filp,
 		       size_t cnt,
 		       loff_t *ppos)
 {
-	struct seq_file *m = filp->private_data;
-	struct i915_error_state_file_priv *error_priv = m->private;
+	struct i915_error_state_file_priv *error_priv = filp->private_data;
 	struct drm_device *dev = error_priv->dev;
 	int ret;
 
@@ -842,25 +1002,81 @@ static int i915_error_state_open(struct inode *inode, struct file *file)
 		kref_get(&error_priv->error->ref);
 	spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
 
-	return single_open(file, i915_error_state, error_priv);
+	file->private_data = error_priv;
+
+	return 0;
 }
 
 static int i915_error_state_release(struct inode *inode, struct file *file)
 {
-	struct seq_file *m = file->private_data;
-	struct i915_error_state_file_priv *error_priv = m->private;
+	struct i915_error_state_file_priv *error_priv = file->private_data;
 
 	if (error_priv->error)
 		kref_put(&error_priv->error->ref, i915_error_state_free);
 	kfree(error_priv);
 
-	return single_release(inode, file);
+	return 0;
+}
+
+static ssize_t i915_error_state_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *pos)
+{
+	struct i915_error_state_file_priv *error_priv = file->private_data;
+	struct drm_i915_error_state_buf error_str;
+	loff_t tmp_pos = 0;
+	ssize_t ret_count = 0;
+	int ret = 0;
+
+	memset(&error_str, 0, sizeof(error_str));
+
+	/* We need to have enough room to store any i915_error_state printf
+	 * so that we can move it to start position.
+	 */
+	error_str.size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
+	error_str.buf = kmalloc(error_str.size,
+				GFP_TEMPORARY | __GFP_NORETRY | __GFP_NOWARN);
+
+	if (error_str.buf == NULL) {
+		error_str.size = PAGE_SIZE;
+		error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
+	}
+
+	if (error_str.buf == NULL) {
+		error_str.size = 128;
+		error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
+	}
+
+	if (error_str.buf == NULL)
+		return -ENOMEM;
+
+	error_str.start = *pos;
+
+	ret = i915_error_state(error_priv, &error_str);
+	if (ret)
+		goto out;
+
+	if (error_str.bytes == 0 && error_str.err) {
+		ret = error_str.err;
+		goto out;
+	}
+
+	ret_count = simple_read_from_buffer(userbuf, count, &tmp_pos,
+					    error_str.buf,
+					    error_str.bytes);
+
+	if (ret_count < 0)
+		ret = ret_count;
+	else
+		*pos = error_str.start + ret_count;
+out:
+	kfree(error_str.buf);
+	return ret ?: ret_count;
 }
 
 static const struct file_operations i915_error_state_fops = {
 	.owner = THIS_MODULE,
 	.open = i915_error_state_open,
-	.read = seq_read,
+	.read = i915_error_state_read,
 	.write = i915_error_state_write,
 	.llseek = default_llseek,
 	.release = i915_error_state_release,
@@ -941,7 +1157,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			   MEMSTAT_VID_SHIFT);
 		seq_printf(m, "Current P-state: %d\n",
 			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
-	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1009,6 +1225,26 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 
 		seq_printf(m, "Max overclocked frequency: %dMHz\n",
 			   dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
+	} else if (IS_VALLEYVIEW(dev)) {
+		u32 freq_sts, val;
+
+		mutex_lock(&dev_priv->rps.hw_lock);
+		freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+		seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
+		seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
+
+		val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1);
+		seq_printf(m, "max GPU freq: %d MHz\n",
+			   vlv_gpu_freq(dev_priv->mem_freq, val));
+
+		val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM);
+		seq_printf(m, "min GPU freq: %d MHz\n",
+			   vlv_gpu_freq(dev_priv->mem_freq, val));
+
+		seq_printf(m, "current GPU freq: %d MHz\n",
+			   vlv_gpu_freq(dev_priv->mem_freq,
+					(freq_sts >> 8) & 0xff));
+		mutex_unlock(&dev_priv->rps.hw_lock);
 	} else {
 		seq_printf(m, "no P-state info available\n");
 	}
@@ -1290,6 +1526,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static int i915_ips_status(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!HAS_IPS(dev)) {
+		seq_puts(m, "not supported\n");
+		return 0;
+	}
+
+	if (I915_READ(IPS_CTL) & IPS_ENABLE)
+		seq_puts(m, "enabled\n");
+	else
+		seq_puts(m, "disabled\n");
+
+	return 0;
+}
+
 static int i915_sr_status(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1642,27 +1897,27 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
 
 	seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_DIV_A));
+		   vlv_dpio_read(dev_priv, _DPIO_DIV_A));
 	seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_DIV_B));
+		   vlv_dpio_read(dev_priv, _DPIO_DIV_B));
 
 	seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_REFSFR_A));
+		   vlv_dpio_read(dev_priv, _DPIO_REFSFR_A));
 	seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_REFSFR_B));
+		   vlv_dpio_read(dev_priv, _DPIO_REFSFR_B));
 
 	seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
+		   vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
 	seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
+		   vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
 
-	seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
-	seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
-		   intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
+	seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
+		   vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_A));
+	seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
+		   vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_B));
 
 	seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
-		   intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
+		   vlv_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
 
 	mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1780,7 +2035,8 @@ i915_drop_caches_set(void *data, u64 val)
 	}
 
 	if (val & DROP_UNBOUND) {
-		list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
+		list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
+					 global_list)
 			if (obj->pages_pin_count == 0) {
 				ret = i915_gem_object_put_pages(obj);
 				if (ret)
@@ -1812,7 +2068,11 @@ i915_max_freq_get(void *data, u64 *val)
 	if (ret)
 		return ret;
 
-	*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+	if (IS_VALLEYVIEW(dev))
+		*val = vlv_gpu_freq(dev_priv->mem_freq,
+				    dev_priv->rps.max_delay);
+	else
+		*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -1837,9 +2097,16 @@ i915_max_freq_set(void *data, u64 val)
 	/*
 	 * Turbo will still be enabled, but won't go above the set value.
 	 */
-	do_div(val, GT_FREQUENCY_MULTIPLIER);
-	dev_priv->rps.max_delay = val;
-	gen6_set_rps(dev, val);
+	if (IS_VALLEYVIEW(dev)) {
+		val = vlv_freq_opcode(dev_priv->mem_freq, val);
+		dev_priv->rps.max_delay = val;
+		gen6_set_rps(dev, val);
+	} else {
+		do_div(val, GT_FREQUENCY_MULTIPLIER);
+		dev_priv->rps.max_delay = val;
+		gen6_set_rps(dev, val);
+	}
+
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -1863,7 +2130,11 @@ i915_min_freq_get(void *data, u64 *val)
 	if (ret)
 		return ret;
 
-	*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+	if (IS_VALLEYVIEW(dev))
+		*val = vlv_gpu_freq(dev_priv->mem_freq,
+				    dev_priv->rps.min_delay);
+	else
+		*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -1888,9 +2159,15 @@ i915_min_freq_set(void *data, u64 val)
 	/*
 	 * Turbo will still be enabled, but won't go below the set value.
 	 */
-	do_div(val, GT_FREQUENCY_MULTIPLIER);
-	dev_priv->rps.min_delay = val;
-	gen6_set_rps(dev, val);
+	if (IS_VALLEYVIEW(dev)) {
+		val = vlv_freq_opcode(dev_priv->mem_freq, val);
+		dev_priv->rps.min_delay = val;
+		valleyview_set_rps(dev, val);
+	} else {
+		do_div(val, GT_FREQUENCY_MULTIPLIER);
+		dev_priv->rps.min_delay = val;
+		gen6_set_rps(dev, val);
+	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -2057,6 +2334,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
 	{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
 	{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
+	{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
 	{"i915_rstdby_delays", i915_rstdby_delays, 0},
 	{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
 	{"i915_delayfreq_table", i915_delayfreq_table, 0},
@@ -2066,6 +2344,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_ring_freq_table", i915_ring_freq_table, 0},
 	{"i915_gfxec", i915_gfxec, 0},
 	{"i915_fbc_status", i915_fbc_status, 0},
+	{"i915_ips_status", i915_ips_status, 0},
 	{"i915_sr_status", i915_sr_status, 0},
 	{"i915_opregion", i915_opregion, 0},
 	{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},

+ 37 - 53
drivers/gpu/drm/i915/i915_dma.c

@@ -42,7 +42,6 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
-#include <asm/pat.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -956,6 +955,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_BLT:
 		value = intel_ring_initialized(&dev_priv->ring[BCS]);
 		break;
+	case I915_PARAM_HAS_VEBOX:
+		value = intel_ring_initialized(&dev_priv->ring[VECS]);
+		break;
 	case I915_PARAM_HAS_RELAXED_FENCING:
 		value = 1;
 		break;
@@ -999,8 +1001,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
 		value = 1;
 		break;
 	default:
-		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
-				 param->param);
+		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
 	}
 
@@ -1359,8 +1360,10 @@ static int i915_load_modeset_init(struct drm_device *dev)
 cleanup_gem:
 	mutex_lock(&dev->struct_mutex);
 	i915_gem_cleanup_ringbuffer(dev);
+	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
 	i915_gem_cleanup_aliasing_ppgtt(dev);
+	drm_mm_takedown(&dev_priv->mm.gtt_space);
 cleanup_irq:
 	drm_irq_uninstall(dev);
 cleanup_gem_stolen:
@@ -1397,29 +1400,6 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
 	master->driver_priv = NULL;
 }
 
-static void
-i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
-		unsigned long size)
-{
-	dev_priv->mm.gtt_mtrr = -1;
-
-#if defined(CONFIG_X86_PAT)
-	if (cpu_has_pat)
-		return;
-#endif
-
-	/* Set up a WC MTRR for non-PAT systems.  This is more common than
-	 * one would think, because the kernel disables PAT on first
-	 * generation Core chips because WC PAT gets overridden by a UC
-	 * MTRR if present.  Even if a UC MTRR isn't present.
-	 */
-	dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
-	if (dev_priv->mm.gtt_mtrr < 0) {
-		DRM_INFO("MTRR allocation failed.  Graphics "
-			 "performance may suffer.\n");
-	}
-}
-
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
 	struct apertures_struct *ap;
@@ -1431,7 +1411,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 		return;
 
 	ap->ranges[0].base = dev_priv->gtt.mappable_base;
-	ap->ranges[0].size = dev_priv->gtt.mappable_end - dev_priv->gtt.start;
+	ap->ranges[0].size = dev_priv->gtt.mappable_end;
 
 	primary =
 		pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
@@ -1445,15 +1425,19 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 {
 	const struct intel_device_info *info = dev_priv->info;
 
-#define DEV_INFO_FLAG(name) info->name ? #name "," : ""
-#define DEV_INFO_SEP ,
+#define PRINT_S(name) "%s"
+#define SEP_EMPTY
+#define PRINT_FLAG(name) info->name ? #name "," : ""
+#define SEP_COMMA ,
 	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
-			 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
 			 info->gen,
 			 dev_priv->dev->pdev->device,
-			 DEV_INFO_FLAGS);
-#undef DEV_INFO_FLAG
-#undef DEV_INFO_SEP
+			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
+#undef PRINT_S
+#undef SEP_EMPTY
+#undef PRINT_FLAG
+#undef SEP_COMMA
 }
 
 /**
@@ -1468,7 +1452,7 @@ static void intel_early_sanitize_regs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (IS_HASWELL(dev))
+	if (HAS_FPGA_DBG_UNCLAIMED(dev))
 		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 }
 
@@ -1574,8 +1558,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto out_rmmap;
 	}
 
-	i915_mtrr_setup(dev_priv, dev_priv->gtt.mappable_base,
-			aperture_size);
+	dev_priv->mm.gtt_mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+						 aperture_size);
 
 	/* The i915 workqueue is primarily used for batched retirement of
 	 * requests (and thus managing bo) once the task has been completed
@@ -1629,6 +1613,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->gpu_error.lock);
 	spin_lock_init(&dev_priv->rps.lock);
+	spin_lock_init(&dev_priv->backlight.lock);
 	mutex_init(&dev_priv->dpio_lock);
 
 	mutex_init(&dev_priv->rps.hw_lock);
@@ -1647,6 +1632,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	/* Start out suspended */
 	dev_priv->mm.suspended = 1;
 
+	if (HAS_POWER_WELL(dev))
+		i915_init_power_well(dev);
+
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		ret = i915_load_modeset_init(dev);
 		if (ret < 0) {
@@ -1679,12 +1667,7 @@ out_gem_unload:
 	intel_teardown_mchbar(dev);
 	destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
-	if (dev_priv->mm.gtt_mtrr >= 0) {
-		mtrr_del(dev_priv->mm.gtt_mtrr,
-			 dev_priv->gtt.mappable_base,
-			 aperture_size);
-		dev_priv->mm.gtt_mtrr = -1;
-	}
+	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
 	io_mapping_free(dev_priv->gtt.mappable);
 	dev_priv->gtt.gtt_remove(dev);
 out_rmmap:
@@ -1703,6 +1686,9 @@ int i915_driver_unload(struct drm_device *dev)
 
 	intel_gpu_ips_teardown();
 
+	if (HAS_POWER_WELL(dev))
+		i915_remove_power_well(dev);
+
 	i915_teardown_sysfs(dev);
 
 	if (dev_priv->mm.inactive_shrinker.shrink)
@@ -1719,12 +1705,7 @@ int i915_driver_unload(struct drm_device *dev)
 	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
 
 	io_mapping_free(dev_priv->gtt.mappable);
-	if (dev_priv->mm.gtt_mtrr >= 0) {
-		mtrr_del(dev_priv->mm.gtt_mtrr,
-			 dev_priv->gtt.mappable_base,
-			 dev_priv->gtt.mappable_end);
-		dev_priv->mm.gtt_mtrr = -1;
-	}
+	arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
 
 	acpi_video_unregister();
 
@@ -1737,10 +1718,10 @@ int i915_driver_unload(struct drm_device *dev)
 		 * free the memory space allocated for the child device
 		 * config parsed from VBT
 		 */
-		if (dev_priv->child_dev && dev_priv->child_dev_num) {
-			kfree(dev_priv->child_dev);
-			dev_priv->child_dev = NULL;
-			dev_priv->child_dev_num = 0;
+		if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
+			kfree(dev_priv->vbt.child_dev);
+			dev_priv->vbt.child_dev = NULL;
+			dev_priv->vbt.child_dev_num = 0;
 		}
 
 		vga_switcheroo_unregister_client(dev->pdev);
@@ -1773,6 +1754,7 @@ int i915_driver_unload(struct drm_device *dev)
 			i915_free_hws(dev);
 	}
 
+	drm_mm_takedown(&dev_priv->mm.gtt_space);
 	if (dev_priv->regs != NULL)
 		pci_iounmap(dev->pdev, dev_priv->regs);
 
@@ -1782,6 +1764,8 @@ int i915_driver_unload(struct drm_device *dev)
 	destroy_workqueue(dev_priv->wq);
 	pm_qos_remove_request(&dev_priv->pm_qos);
 
+	dev_priv->gtt.gtt_remove(dev);
+
 	if (dev_priv->slab)
 		kmem_cache_destroy(dev_priv->slab);
 
@@ -1796,7 +1780,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
 	struct drm_i915_file_private *file_priv;
 
 	DRM_DEBUG_DRIVER("\n");
-	file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
+	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
 	if (!file_priv)
 		return -ENOMEM;
 

+ 61 - 55
drivers/gpu/drm/i915/i915_drv.c

@@ -128,6 +128,10 @@ module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
 MODULE_PARM_DESC(disable_power_well,
 		 "Disable the power well when possible (default: false)");
 
+int i915_enable_ips __read_mostly = 1;
+module_param_named(enable_ips, i915_enable_ips, int, 0600);
+MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -280,6 +284,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
 	GEN7_FEATURES,
 	.is_ivybridge = 1,
 	.is_mobile = 1,
+	.has_fbc = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
@@ -308,12 +313,19 @@ static const struct intel_device_info intel_valleyview_d_info = {
 static const struct intel_device_info intel_haswell_d_info = {
 	GEN7_FEATURES,
 	.is_haswell = 1,
+	.has_ddi = 1,
+	.has_fpga_dbg = 1,
+	.has_vebox_ring = 1,
 };
 
 static const struct intel_device_info intel_haswell_m_info = {
 	GEN7_FEATURES,
 	.is_haswell = 1,
 	.is_mobile = 1,
+	.has_ddi = 1,
+	.has_fpga_dbg = 1,
+	.has_fbc = 1,
+	.has_vebox_ring = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {		/* aka */
@@ -445,7 +457,6 @@ void intel_detect_pch(struct drm_device *dev)
 	 */
 	if (INTEL_INFO(dev)->num_pipes == 0) {
 		dev_priv->pch_type = PCH_NOP;
-		dev_priv->num_pch_pll = 0;
 		return;
 	}
 
@@ -454,9 +465,15 @@ void intel_detect_pch(struct drm_device *dev)
 	 * make graphics device passthrough work easy for VMM, that only
 	 * need to expose ISA bridge to let driver know the real hardware
 	 * underneath. This is a requirement from virtualization team.
+	 *
+	 * In some virtualized environments (e.g. XEN), there is irrelevant
+	 * ISA bridge in the system. To work reliably, we should scan trhough
+	 * all the ISA bridge devices and check for the first match, instead
+	 * of only checking the first one.
 	 */
 	pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-	if (pch) {
+	while (pch) {
+		struct pci_dev *curr = pch;
 		if (pch->vendor == PCI_VENDOR_ID_INTEL) {
 			unsigned short id;
 			id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
@@ -464,37 +481,39 @@ void intel_detect_pch(struct drm_device *dev)
 
 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_IBX;
-				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
 				WARN_ON(!IS_GEN5(dev));
 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_CPT;
-				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
 				/* PantherPoint is CPT compatible */
 				dev_priv->pch_type = PCH_CPT;
-				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found PatherPoint PCH\n");
 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_LPT;
-				dev_priv->num_pch_pll = 0;
 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
 				WARN_ON(!IS_HASWELL(dev));
 				WARN_ON(IS_ULT(dev));
 			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_LPT;
-				dev_priv->num_pch_pll = 0;
 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
 				WARN_ON(!IS_HASWELL(dev));
 				WARN_ON(!IS_ULT(dev));
+			} else {
+				goto check_next;
 			}
-			BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
+			pci_dev_put(pch);
+			break;
 		}
-		pci_dev_put(pch);
+check_next:
+		pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
+		pci_dev_put(curr);
 	}
+	if (!pch)
+		DRM_DEBUG_KMS("No PCH found?\n");
 }
 
 bool i915_semaphore_is_enabled(struct drm_device *dev)
@@ -549,6 +568,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 		 */
 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 			dev_priv->display.crtc_disable(crtc);
+
+		intel_modeset_suspend_hw(dev);
 	}
 
 	i915_save_state(dev);
@@ -556,7 +577,7 @@ static int i915_drm_freeze(struct drm_device *dev)
 	intel_opregion_fini(dev);
 
 	console_lock();
-	intel_fbdev_set_suspend(dev, 1);
+	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
 	console_unlock();
 
 	return 0;
@@ -600,7 +621,7 @@ void intel_console_resume(struct work_struct *work)
 	struct drm_device *dev = dev_priv->dev;
 
 	console_lock();
-	intel_fbdev_set_suspend(dev, 0);
+	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
 	console_unlock();
 }
 
@@ -669,7 +690,7 @@ static int __i915_drm_thaw(struct drm_device *dev)
 	 * path of resume if possible.
 	 */
 	if (console_trylock()) {
-		intel_fbdev_set_suspend(dev, 0);
+		intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
 		console_unlock();
 	} else {
 		schedule_work(&dev_priv->console_resume_work);
@@ -855,37 +876,14 @@ static int gen6_do_reset(struct drm_device *dev)
 
 int intel_gpu_reset(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret = -ENODEV;
-
 	switch (INTEL_INFO(dev)->gen) {
 	case 7:
-	case 6:
-		ret = gen6_do_reset(dev);
-		break;
-	case 5:
-		ret = ironlake_do_reset(dev);
-		break;
-	case 4:
-		ret = i965_do_reset(dev);
-		break;
-	case 2:
-		ret = i8xx_do_reset(dev);
-		break;
-	}
-
-	/* Also reset the gpu hangman. */
-	if (dev_priv->gpu_error.stop_rings) {
-		DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
-		dev_priv->gpu_error.stop_rings = 0;
-		if (ret == -ENODEV) {
-			DRM_ERROR("Reset not implemented, but ignoring "
-				  "error for simulated gpu hangs\n");
-			ret = 0;
-		}
+	case 6: return gen6_do_reset(dev);
+	case 5: return ironlake_do_reset(dev);
+	case 4: return i965_do_reset(dev);
+	case 2: return i8xx_do_reset(dev);
+	default: return -ENODEV;
 	}
-
-	return ret;
 }
 
 /**
@@ -906,6 +904,7 @@ int intel_gpu_reset(struct drm_device *dev)
 int i915_reset(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	bool simulated;
 	int ret;
 
 	if (!i915_try_reset)
@@ -915,13 +914,26 @@ int i915_reset(struct drm_device *dev)
 
 	i915_gem_reset(dev);
 
-	ret = -ENODEV;
-	if (get_seconds() - dev_priv->gpu_error.last_reset < 5)
+	simulated = dev_priv->gpu_error.stop_rings != 0;
+
+	if (!simulated && get_seconds() - dev_priv->gpu_error.last_reset < 5) {
 		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
-	else
+		ret = -ENODEV;
+	} else {
 		ret = intel_gpu_reset(dev);
 
-	dev_priv->gpu_error.last_reset = get_seconds();
+		/* Also reset the gpu hangman. */
+		if (simulated) {
+			DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
+			dev_priv->gpu_error.stop_rings = 0;
+			if (ret == -ENODEV) {
+				DRM_ERROR("Reset not implemented, but ignoring "
+					  "error for simulated gpu hangs\n");
+				ret = 0;
+			}
+		} else
+			dev_priv->gpu_error.last_reset = get_seconds();
+	}
 	if (ret) {
 		DRM_ERROR("Failed to reset chip.\n");
 		mutex_unlock(&dev->struct_mutex);
@@ -984,12 +996,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct intel_device_info *intel_info =
 		(struct intel_device_info *) ent->driver_data;
 
-	if (intel_info->is_valleyview)
-		if(!i915_preliminary_hw_support) {
-			DRM_ERROR("Preliminary hardware support disabled\n");
-			return -ENODEV;
-		}
-
 	/* Only bind to function 0 of the device. Early generations
 	 * used function 1 as a placeholder for multi-head. This causes
 	 * us confusion instead, especially on the systems where both
@@ -1218,16 +1224,16 @@ MODULE_LICENSE("GPL and additional rights");
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
 {
-	/* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the
-	 * chip from rc6 before touching it for real. MI_MODE is masked, hence
-	 * harmless to write 0 into. */
+	/* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
+	 * the chip from rc6 before touching it for real. MI_MODE is masked,
+	 * hence harmless to write 0 into. */
 	I915_WRITE_NOTRACE(MI_MODE, 0);
 }
 
 static void
 hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
 {
-	if (IS_HASWELL(dev_priv->dev) &&
+	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
 	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
 		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
 			  reg);
@@ -1238,7 +1244,7 @@ hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
 static void
 hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
 {
-	if (IS_HASWELL(dev_priv->dev) &&
+	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
 	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
 		DRM_ERROR("Unclaimed write to %x\n", reg);
 		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);

+ 249 - 110
drivers/gpu/drm/i915/i915_drv.h

@@ -76,6 +76,8 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
+#define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A')
+
 enum port {
 	PORT_A = 0,
 	PORT_B,
@@ -86,6 +88,24 @@ enum port {
 };
 #define port_name(p) ((p) + 'A')
 
+enum intel_display_power_domain {
+	POWER_DOMAIN_PIPE_A,
+	POWER_DOMAIN_PIPE_B,
+	POWER_DOMAIN_PIPE_C,
+	POWER_DOMAIN_PIPE_A_PANEL_FITTER,
+	POWER_DOMAIN_PIPE_B_PANEL_FITTER,
+	POWER_DOMAIN_PIPE_C_PANEL_FITTER,
+	POWER_DOMAIN_TRANSCODER_A,
+	POWER_DOMAIN_TRANSCODER_B,
+	POWER_DOMAIN_TRANSCODER_C,
+	POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF,
+};
+
+#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
+#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
+		((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
+#define POWER_DOMAIN_TRANSCODER(tran) ((tran) + POWER_DOMAIN_TRANSCODER_A)
+
 enum hpd_pin {
 	HPD_NONE = 0,
 	HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
@@ -112,15 +132,38 @@ enum hpd_pin {
 	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
 		if ((intel_encoder)->base.crtc == (__crtc))
 
-struct intel_pch_pll {
+struct drm_i915_private;
+
+enum intel_dpll_id {
+	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
+	/* real shared dpll ids must be >= 0 */
+	DPLL_ID_PCH_PLL_A,
+	DPLL_ID_PCH_PLL_B,
+};
+#define I915_NUM_PLLS 2
+
+struct intel_dpll_hw_state {
+	uint32_t dpll;
+	uint32_t fp0;
+	uint32_t fp1;
+};
+
+struct intel_shared_dpll {
 	int refcount; /* count of number of CRTCs sharing this PLL */
 	int active; /* count of number of active CRTCs (i.e. DPMS on) */
 	bool on; /* is the PLL actually active? Disabled during modeset */
-	int pll_reg;
-	int fp0_reg;
-	int fp1_reg;
+	const char *name;
+	/* should match the index in the dev_priv->shared_dplls array */
+	enum intel_dpll_id id;
+	struct intel_dpll_hw_state hw_state;
+	void (*enable)(struct drm_i915_private *dev_priv,
+		       struct intel_shared_dpll *pll);
+	void (*disable)(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll);
+	bool (*get_hw_state)(struct drm_i915_private *dev_priv,
+			     struct intel_shared_dpll *pll,
+			     struct intel_dpll_hw_state *hw_state);
 };
-#define I915_NUM_PLLS 2
 
 /* Used by dp and fdi links */
 struct intel_link_m_n {
@@ -175,7 +218,6 @@ struct opregion_header;
 struct opregion_acpi;
 struct opregion_swsci;
 struct opregion_asle;
-struct drm_i915_private;
 
 struct intel_opregion {
 	struct opregion_header __iomem *header;
@@ -286,6 +328,8 @@ struct drm_i915_error_state {
 
 struct intel_crtc_config;
 struct intel_crtc;
+struct intel_limit;
+struct dpll;
 
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
@@ -293,11 +337,28 @@ struct drm_i915_display_funcs {
 	void (*disable_fbc)(struct drm_device *dev);
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
+	/**
+	 * find_dpll() - Find the best values for the PLL
+	 * @limit: limits for the PLL
+	 * @crtc: current CRTC
+	 * @target: target frequency in kHz
+	 * @refclk: reference clock frequency in kHz
+	 * @match_clock: if provided, @best_clock P divider must
+	 *               match the P divider from @match_clock
+	 *               used for LVDS downclocking
+	 * @best_clock: best PLL values found
+	 *
+	 * Returns true on success, false on failure.
+	 */
+	bool (*find_dpll)(const struct intel_limit *limit,
+			  struct drm_crtc *crtc,
+			  int target, int refclk,
+			  struct dpll *match_clock,
+			  struct dpll *best_clock);
 	void (*update_wm)(struct drm_device *dev);
 	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
-				 uint32_t sprite_width, int pixel_size);
-	void (*update_linetime_wm)(struct drm_device *dev, int pipe,
-				 struct drm_display_mode *mode);
+				 uint32_t sprite_width, int pixel_size,
+				 bool enable);
 	void (*modeset_global_resources)(struct drm_device *dev);
 	/* Returns the active state of the crtc, and if the crtc is active,
 	 * fills out the pipe-config with the hw state. */
@@ -331,68 +392,56 @@ struct drm_i915_gt_funcs {
 	void (*force_wake_put)(struct drm_i915_private *dev_priv);
 };
 
-#define DEV_INFO_FLAGS \
-	DEV_INFO_FLAG(is_mobile) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_i85x) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_i915g) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_i945gm) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_g33) DEV_INFO_SEP \
-	DEV_INFO_FLAG(need_gfx_hws) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_g4x) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_pineview) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_broadwater) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_crestline) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_ivybridge) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_valleyview) DEV_INFO_SEP \
-	DEV_INFO_FLAG(is_haswell) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_force_wake) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_fbc) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_pipe_cxsr) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_hotplug) DEV_INFO_SEP \
-	DEV_INFO_FLAG(cursor_needs_physical) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_overlay) DEV_INFO_SEP \
-	DEV_INFO_FLAG(overlay_needs_physical) DEV_INFO_SEP \
-	DEV_INFO_FLAG(supports_tv) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_bsd_ring) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_blt_ring) DEV_INFO_SEP \
-	DEV_INFO_FLAG(has_llc)
+#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
+	func(is_mobile) sep \
+	func(is_i85x) sep \
+	func(is_i915g) sep \
+	func(is_i945gm) sep \
+	func(is_g33) sep \
+	func(need_gfx_hws) sep \
+	func(is_g4x) sep \
+	func(is_pineview) sep \
+	func(is_broadwater) sep \
+	func(is_crestline) sep \
+	func(is_ivybridge) sep \
+	func(is_valleyview) sep \
+	func(is_haswell) sep \
+	func(has_force_wake) sep \
+	func(has_fbc) sep \
+	func(has_pipe_cxsr) sep \
+	func(has_hotplug) sep \
+	func(cursor_needs_physical) sep \
+	func(has_overlay) sep \
+	func(overlay_needs_physical) sep \
+	func(supports_tv) sep \
+	func(has_bsd_ring) sep \
+	func(has_blt_ring) sep \
+	func(has_vebox_ring) sep \
+	func(has_llc) sep \
+	func(has_ddi) sep \
+	func(has_fpga_dbg)
+
+#define DEFINE_FLAG(name) u8 name:1
+#define SEP_SEMICOLON ;
 
 struct intel_device_info {
 	u32 display_mmio_offset;
 	u8 num_pipes:3;
 	u8 gen;
-	u8 is_mobile:1;
-	u8 is_i85x:1;
-	u8 is_i915g:1;
-	u8 is_i945gm:1;
-	u8 is_g33:1;
-	u8 need_gfx_hws:1;
-	u8 is_g4x:1;
-	u8 is_pineview:1;
-	u8 is_broadwater:1;
-	u8 is_crestline:1;
-	u8 is_ivybridge:1;
-	u8 is_valleyview:1;
-	u8 has_force_wake:1;
-	u8 is_haswell:1;
-	u8 has_fbc:1;
-	u8 has_pipe_cxsr:1;
-	u8 has_hotplug:1;
-	u8 cursor_needs_physical:1;
-	u8 has_overlay:1;
-	u8 overlay_needs_physical:1;
-	u8 supports_tv:1;
-	u8 has_bsd_ring:1;
-	u8 has_blt_ring:1;
-	u8 has_llc:1;
+	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
 };
 
+#undef DEFINE_FLAG
+#undef SEP_SEMICOLON
+
 enum i915_cache_level {
 	I915_CACHE_NONE = 0,
 	I915_CACHE_LLC,
 	I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */
 };
 
+typedef uint32_t gen6_gtt_pte_t;
+
 /* The Graphics Translation Table is the way in which GEN hardware translates a
  * Graphics Virtual Address into a Physical Address. In addition to the normal
  * collateral associated with any va->pa translations GEN hardware also has a
@@ -428,6 +477,9 @@ struct i915_gtt {
 				   struct sg_table *st,
 				   unsigned int pg_start,
 				   enum i915_cache_level cache_level);
+	gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
+				     dma_addr_t addr,
+				     enum i915_cache_level level);
 };
 #define gtt_total_entries(gtt) ((gtt).total >> PAGE_SHIFT)
 
@@ -449,19 +501,31 @@ struct i915_hw_ppgtt {
 			       struct sg_table *st,
 			       unsigned int pg_start,
 			       enum i915_cache_level cache_level);
+	gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
+				     dma_addr_t addr,
+				     enum i915_cache_level level);
 	int (*enable)(struct drm_device *dev);
 	void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
 };
 
+struct i915_ctx_hang_stats {
+	/* This context had batch pending when hang was declared */
+	unsigned batch_pending;
+
+	/* This context had batch active when hang was declared */
+	unsigned batch_active;
+};
 
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_ID 0
 struct i915_hw_context {
+	struct kref ref;
 	int id;
 	bool is_initialized;
 	struct drm_i915_file_private *file_priv;
 	struct intel_ring_buffer *ring;
 	struct drm_i915_gem_object *obj;
+	struct i915_ctx_hang_stats hang_stats;
 };
 
 enum no_fbc_reason {
@@ -658,6 +722,7 @@ struct i915_suspend_saved_registers {
 
 struct intel_gen6_power_mgmt {
 	struct work_struct work;
+	struct delayed_work vlv_work;
 	u32 pm_iir;
 	/* lock - irqsave spinlock that protectects the work_struct and
 	 * pm_iir. */
@@ -668,6 +733,7 @@ struct intel_gen6_power_mgmt {
 	u8 cur_delay;
 	u8 min_delay;
 	u8 max_delay;
+	u8 rpe_delay;
 	u8 hw_max;
 
 	struct delayed_work delayed_resume_work;
@@ -704,6 +770,15 @@ struct intel_ilk_power_mgmt {
 	struct drm_i915_gem_object *renderctx;
 };
 
+/* Power well structure for haswell */
+struct i915_power_well {
+	struct drm_device *device;
+	spinlock_t lock;
+	/* power well enable/disable usage count */
+	int count;
+	int i915_request;
+};
+
 struct i915_dri1_state {
 	unsigned allow_batchbuffer : 1;
 	u32 __iomem *gfx_hws_cpu_addr;
@@ -812,14 +887,20 @@ struct i915_gem_mm {
 	u32 object_count;
 };
 
+struct drm_i915_error_state_buf {
+	unsigned bytes;
+	unsigned size;
+	int err;
+	u8 *buf;
+	loff_t start;
+	loff_t pos;
+};
+
 struct i915_gpu_error {
 	/* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
 #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
 	struct timer_list hangcheck_timer;
-	int hangcheck_count;
-	uint32_t last_acthd[I915_NUM_RINGS];
-	uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
 
 	/* For reset and error_state handling. */
 	spinlock_t lock;
@@ -875,6 +956,37 @@ enum modeset_restore {
 	MODESET_SUSPENDED,
 };
 
+struct intel_vbt_data {
+	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
+	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
+
+	/* Feature bits */
+	unsigned int int_tv_support:1;
+	unsigned int lvds_dither:1;
+	unsigned int lvds_vbt:1;
+	unsigned int int_crt_support:1;
+	unsigned int lvds_use_ssc:1;
+	unsigned int display_clock_mode:1;
+	unsigned int fdi_rx_polarity_inverted:1;
+	int lvds_ssc_freq;
+	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
+
+	/* eDP */
+	int edp_rate;
+	int edp_lanes;
+	int edp_preemphasis;
+	int edp_vswing;
+	bool edp_initialized;
+	bool edp_support;
+	int edp_bpp;
+	struct edp_power_seq edp_pps;
+
+	int crt_ddc_pin;
+
+	int child_dev_num;
+	struct child_device_config *child_dev;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
@@ -941,9 +1053,9 @@ typedef struct drm_i915_private {
 			HPD_MARK_DISABLED = 2
 		} hpd_mark;
 	} hpd_stats[HPD_NUM_PINS];
+	u32 hpd_event_bits;
 	struct timer_list hotplug_reenable_timer;
 
-	int num_pch_pll;
 	int num_plane;
 
 	unsigned long cfb_size;
@@ -953,6 +1065,7 @@ typedef struct drm_i915_private {
 	struct intel_fbc_work *fbc_work;
 
 	struct intel_opregion opregion;
+	struct intel_vbt_data vbt;
 
 	/* overlay */
 	struct intel_overlay *overlay;
@@ -962,37 +1075,15 @@ typedef struct drm_i915_private {
 	struct {
 		int level;
 		bool enabled;
+		spinlock_t lock; /* bl registers and the above bl fields */
 		struct backlight_device *device;
 	} backlight;
 
 	/* LVDS info */
 	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
 	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
-
-	/* Feature bits from the VBIOS */
-	unsigned int int_tv_support:1;
-	unsigned int lvds_dither:1;
-	unsigned int lvds_vbt:1;
-	unsigned int int_crt_support:1;
-	unsigned int lvds_use_ssc:1;
-	unsigned int display_clock_mode:1;
-	unsigned int fdi_rx_polarity_inverted:1;
-	int lvds_ssc_freq;
-	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
-	struct {
-		int rate;
-		int lanes;
-		int preemphasis;
-		int vswing;
-
-		bool initialized;
-		bool support;
-		int bpp;
-		struct edp_power_seq pps;
-	} edp;
 	bool no_aux_handshake;
 
-	int crt_ddc_pin;
 	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@@ -1020,16 +1111,13 @@ typedef struct drm_i915_private {
 	/* Kernel Modesetting */
 
 	struct sdvo_device_mapping sdvo_mappings[2];
-	/* indicate whether the LVDS_BORDER should be enabled or not */
-	unsigned int lvds_border_bits;
-	/* Panel fitter placement and size for Ironlake+ */
-	u32 pch_pf_pos, pch_pf_size;
 
 	struct drm_crtc *plane_to_crtc_mapping[3];
 	struct drm_crtc *pipe_to_crtc_mapping[3];
 	wait_queue_head_t pending_flip_queue;
 
-	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
+	int num_shared_dpll;
+	struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
 	struct intel_ddi_plls ddi_plls;
 
 	/* Reclocking support */
@@ -1038,8 +1126,6 @@ typedef struct drm_i915_private {
 	/* indicates the reduced downclock for LVDS*/
 	int lvds_downclock;
 	u16 orig_clock;
-	int child_dev_num;
-	struct child_device_config *child_dev;
 
 	bool mchbar_need_disable;
 
@@ -1052,6 +1138,9 @@ typedef struct drm_i915_private {
 	 * mchdev_lock in intel_pm.c */
 	struct intel_ilk_power_mgmt ips;
 
+	/* Haswell power well */
+	struct i915_power_well power_well;
+
 	enum no_fbc_reason no_fbc_reason;
 
 	struct drm_mm_node *compressed_fb;
@@ -1059,6 +1148,8 @@ typedef struct drm_i915_private {
 
 	struct i915_gpu_error gpu_error;
 
+	struct drm_i915_gem_object *vlv_pctx;
+
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
 
@@ -1124,7 +1215,7 @@ struct drm_i915_gem_object {
 	struct drm_mm_node *gtt_space;
 	/** Stolen memory for this object, instead of being backed by shmem. */
 	struct drm_mm_node *stolen;
-	struct list_head gtt_list;
+	struct list_head global_list;
 
 	/** This object's place on the active/inactive lists */
 	struct list_head ring_list;
@@ -1271,9 +1362,18 @@ struct drm_i915_gem_request {
 	/** GEM sequence number associated with this request. */
 	uint32_t seqno;
 
-	/** Postion in the ringbuffer of the end of the request */
+	/** Position in the ringbuffer of the start of the request */
+	u32 head;
+
+	/** Position in the ringbuffer of the end of the request */
 	u32 tail;
 
+	/** Context related to this request */
+	struct i915_hw_context *ctx;
+
+	/** Batch buffer related to this request if any */
+	struct drm_i915_gem_object *batch_obj;
+
 	/** Time at which this request was emitted, in jiffies. */
 	unsigned long emitted_jiffies;
 
@@ -1291,6 +1391,8 @@ struct drm_i915_file_private {
 		struct list_head request_list;
 	} mm;
 	struct idr context_idr;
+
+	struct i915_ctx_hang_stats hang_stats;
 };
 
 #define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
@@ -1341,6 +1443,7 @@ struct drm_i915_file_private {
 
 #define HAS_BSD(dev)            (INTEL_INFO(dev)->has_bsd_ring)
 #define HAS_BLT(dev)            (INTEL_INFO(dev)->has_blt_ring)
+#define HAS_VEBOX(dev)          (INTEL_INFO(dev)->has_vebox_ring)
 #define HAS_LLC(dev)            (INTEL_INFO(dev)->has_llc)
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
@@ -1371,10 +1474,13 @@ struct drm_i915_file_private {
 #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
 #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 
+#define HAS_IPS(dev)		(IS_ULT(dev))
+
 #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
 
-#define HAS_DDI(dev)		(IS_HASWELL(dev))
+#define HAS_DDI(dev)		(INTEL_INFO(dev)->has_ddi)
 #define HAS_POWER_WELL(dev)	(IS_HASWELL(dev))
+#define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
@@ -1435,6 +1541,7 @@ extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
+extern int i915_enable_ips __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1486,8 +1593,6 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
-void intel_enable_asle(struct drm_device *dev);
-
 #ifdef CONFIG_DEBUG_FS
 extern void i915_destroy_error_state(struct drm_device *dev);
 #else
@@ -1626,6 +1731,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj)
 {
 	if (obj->fence_reg != I915_FENCE_REG_NONE) {
 		struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+		WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count <= 0);
 		dev_priv->fence_regs[obj->fence_reg].pin_count--;
 	}
 }
@@ -1658,9 +1764,12 @@ void i915_gem_init_swizzling(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
-int i915_add_request(struct intel_ring_buffer *ring,
-		     struct drm_file *file,
-		     u32 *seqno);
+int __i915_add_request(struct intel_ring_buffer *ring,
+		       struct drm_file *file,
+		       struct drm_i915_gem_object *batch_obj,
+		       u32 *seqno);
+#define i915_add_request(ring, seqno) \
+	__i915_add_request(ring, NULL, NULL, seqno)
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 				 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
@@ -1705,6 +1814,21 @@ void i915_gem_context_fini(struct drm_device *dev);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct intel_ring_buffer *ring,
 			struct drm_file *file, int to_id);
+void i915_gem_context_free(struct kref *ctx_ref);
+static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
+{
+	kref_get(&ctx->ref);
+}
+
+static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
+{
+	kref_put(&ctx->ref, i915_gem_context_free);
+}
+
+struct i915_ctx_hang_stats * __must_check
+i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+				struct drm_file *file,
+				u32 id);
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file);
 int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
@@ -1786,6 +1910,8 @@ void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
 /* i915_debugfs.c */
 int i915_debugfs_init(struct drm_minor *minor);
 void i915_debugfs_cleanup(struct drm_minor *minor);
+__printf(2, 3)
+void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
 
 /* i915_suspend.c */
 extern int i915_save_state(struct drm_device *dev);
@@ -1802,7 +1928,7 @@ void i915_teardown_sysfs(struct drm_device *dev_priv);
 /* intel_i2c.c */
 extern int intel_setup_gmbus(struct drm_device *dev);
 extern void intel_teardown_gmbus(struct drm_device *dev);
-extern inline bool intel_gmbus_is_port_valid(unsigned port)
+static inline bool intel_gmbus_is_port_valid(unsigned port)
 {
 	return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD);
 }
@@ -1811,7 +1937,7 @@ extern struct i2c_adapter *intel_gmbus_get_adapter(
 		struct drm_i915_private *dev_priv, unsigned port);
 extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
 extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
-extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
+static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
 {
 	return container_of(adapter, struct intel_gmbus, adapter)->force_bit;
 }
@@ -1823,14 +1949,10 @@ extern int intel_opregion_setup(struct drm_device *dev);
 extern void intel_opregion_init(struct drm_device *dev);
 extern void intel_opregion_fini(struct drm_device *dev);
 extern void intel_opregion_asle_intr(struct drm_device *dev);
-extern void intel_opregion_gse_intr(struct drm_device *dev);
-extern void intel_opregion_enable_asle(struct drm_device *dev);
 #else
 static inline void intel_opregion_init(struct drm_device *dev) { return; }
 static inline void intel_opregion_fini(struct drm_device *dev) { return; }
 static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
-static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; }
-static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; }
 #endif
 
 /* intel_acpi.c */
@@ -1844,6 +1966,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }
 
 /* modesetting */
 extern void intel_modeset_init_hw(struct drm_device *dev);
+extern void intel_modeset_suspend_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
@@ -1856,6 +1979,9 @@ extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void intel_init_pch_refclk(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
+extern void valleyview_set_rps(struct drm_device *dev, u8 val);
+extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv);
+extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv);
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 extern int intel_enable_rc6(const struct drm_device *dev);
@@ -1867,10 +1993,11 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
-extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
+extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
+					    struct intel_overlay_error_state *error);
 
 extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
-extern void intel_display_print_error_state(struct seq_file *m,
+extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
 					    struct drm_device *dev,
 					    struct intel_display_error_state *error);
 #endif
@@ -1885,8 +2012,20 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
-int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val);
-int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
+
+/* intel_sideband.c */
+u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr);
+void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
+u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
+u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg);
+void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val);
+u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
+		   enum intel_sbi_destination destination);
+void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
+		     enum intel_sbi_destination destination);
+
+int vlv_gpu_freq(int ddr_freq, int val);
+int vlv_freq_opcode(int ddr_freq, int val);
 
 #define __i915_read(x, y) \
 	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);

+ 224 - 69
drivers/gpu/drm/i915/i915_gem.c

@@ -176,7 +176,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 
 	pinned = 0;
 	mutex_lock(&dev->struct_mutex);
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
 		if (obj->pin_count)
 			pinned += obj->gtt_space->size;
 	mutex_unlock(&dev->struct_mutex);
@@ -956,7 +956,7 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
 
 	ret = 0;
 	if (seqno == ring->outstanding_lazy_request)
-		ret = i915_add_request(ring, NULL, NULL);
+		ret = i915_add_request(ring, NULL);
 
 	return ret;
 }
@@ -1087,6 +1087,25 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
 			    interruptible, NULL);
 }
 
+static int
+i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj,
+				     struct intel_ring_buffer *ring)
+{
+	i915_gem_retire_requests_ring(ring);
+
+	/* Manually manage the write flush as we may have not yet
+	 * retired the buffer.
+	 *
+	 * Note that the last_write_seqno is always the earlier of
+	 * the two (read/write) seqno, so if we haved successfully waited,
+	 * we know we have passed the last write.
+	 */
+	obj->last_write_seqno = 0;
+	obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
+
+	return 0;
+}
+
 /**
  * Ensures that all rendering to the object has completed and the object is
  * safe to unbind from the GTT or access from the CPU.
@@ -1107,18 +1126,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
 	if (ret)
 		return ret;
 
-	i915_gem_retire_requests_ring(ring);
-
-	/* Manually manage the write flush as we may have not yet
-	 * retired the buffer.
-	 */
-	if (obj->last_write_seqno &&
-	    i915_seqno_passed(seqno, obj->last_write_seqno)) {
-		obj->last_write_seqno = 0;
-		obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
-	}
-
-	return 0;
+	return i915_gem_object_wait_rendering__tail(obj, ring);
 }
 
 /* A nonblocking variant of the above wait. This is a highly dangerous routine
@@ -1154,19 +1162,10 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
 	mutex_unlock(&dev->struct_mutex);
 	ret = __wait_seqno(ring, seqno, reset_counter, true, NULL);
 	mutex_lock(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
-	i915_gem_retire_requests_ring(ring);
-
-	/* Manually manage the write flush as we may have not yet
-	 * retired the buffer.
-	 */
-	if (obj->last_write_seqno &&
-	    i915_seqno_passed(seqno, obj->last_write_seqno)) {
-		obj->last_write_seqno = 0;
-		obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
-	}
-
-	return ret;
+	return i915_gem_object_wait_rendering__tail(obj, ring);
 }
 
 /**
@@ -1676,7 +1675,7 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
 	/* ->put_pages might need to allocate memory for the bit17 swizzle
 	 * array, hence protect them from being reaped by removing them from gtt
 	 * lists early. */
-	list_del(&obj->gtt_list);
+	list_del(&obj->global_list);
 
 	ops->put_pages(obj);
 	obj->pages = NULL;
@@ -1696,7 +1695,7 @@ __i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
 
 	list_for_each_entry_safe(obj, next,
 				 &dev_priv->mm.unbound_list,
-				 gtt_list) {
+				 global_list) {
 		if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
 		    i915_gem_object_put_pages(obj) == 0) {
 			count += obj->base.size >> PAGE_SHIFT;
@@ -1733,7 +1732,8 @@ i915_gem_shrink_all(struct drm_i915_private *dev_priv)
 
 	i915_gem_evict_everything(dev_priv->dev);
 
-	list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
+	list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
+				 global_list)
 		i915_gem_object_put_pages(obj);
 }
 
@@ -1867,7 +1867,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	if (ret)
 		return ret;
 
-	list_add_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
+	list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 	return 0;
 }
 
@@ -2005,17 +2005,18 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
 	return 0;
 }
 
-int
-i915_add_request(struct intel_ring_buffer *ring,
-		 struct drm_file *file,
-		 u32 *out_seqno)
+int __i915_add_request(struct intel_ring_buffer *ring,
+		       struct drm_file *file,
+		       struct drm_i915_gem_object *obj,
+		       u32 *out_seqno)
 {
 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	struct drm_i915_gem_request *request;
-	u32 request_ring_position;
+	u32 request_ring_position, request_start;
 	int was_empty;
 	int ret;
 
+	request_start = intel_ring_get_tail(ring);
 	/*
 	 * Emit any outstanding flushes - execbuf can fail to emit the flush
 	 * after having emitted the batchbuffer command. Hence we need to fix
@@ -2047,7 +2048,21 @@ i915_add_request(struct intel_ring_buffer *ring,
 
 	request->seqno = intel_ring_get_seqno(ring);
 	request->ring = ring;
+	request->head = request_start;
 	request->tail = request_ring_position;
+	request->ctx = ring->last_context;
+	request->batch_obj = obj;
+
+	/* Whilst this request exists, batch_obj will be on the
+	 * active_list, and so will hold the active reference. Only when this
+	 * request is retired will the the batch_obj be moved onto the
+	 * inactive_list and lose its active reference. Hence we do not need
+	 * to explicitly hold another reference here.
+	 */
+
+	if (request->ctx)
+		i915_gem_context_reference(request->ctx);
+
 	request->emitted_jiffies = jiffies;
 	was_empty = list_empty(&ring->request_list);
 	list_add_tail(&request->list, &ring->request_list);
@@ -2100,9 +2115,114 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
 	spin_unlock(&file_priv->mm.lock);
 }
 
+static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+{
+	if (acthd >= obj->gtt_offset &&
+	    acthd < obj->gtt_offset + obj->base.size)
+		return true;
+
+	return false;
+}
+
+static bool i915_head_inside_request(const u32 acthd_unmasked,
+				     const u32 request_start,
+				     const u32 request_end)
+{
+	const u32 acthd = acthd_unmasked & HEAD_ADDR;
+
+	if (request_start < request_end) {
+		if (acthd >= request_start && acthd < request_end)
+			return true;
+	} else if (request_start > request_end) {
+		if (acthd >= request_start || acthd < request_end)
+			return true;
+	}
+
+	return false;
+}
+
+static bool i915_request_guilty(struct drm_i915_gem_request *request,
+				const u32 acthd, bool *inside)
+{
+	/* There is a possibility that unmasked head address
+	 * pointing inside the ring, matches the batch_obj address range.
+	 * However this is extremely unlikely.
+	 */
+
+	if (request->batch_obj) {
+		if (i915_head_inside_object(acthd, request->batch_obj)) {
+			*inside = true;
+			return true;
+		}
+	}
+
+	if (i915_head_inside_request(acthd, request->head, request->tail)) {
+		*inside = false;
+		return true;
+	}
+
+	return false;
+}
+
+static void i915_set_reset_status(struct intel_ring_buffer *ring,
+				  struct drm_i915_gem_request *request,
+				  u32 acthd)
+{
+	struct i915_ctx_hang_stats *hs = NULL;
+	bool inside, guilty;
+
+	/* Innocent until proven guilty */
+	guilty = false;
+
+	if (ring->hangcheck.action != wait &&
+	    i915_request_guilty(request, acthd, &inside)) {
+		DRM_ERROR("%s hung %s bo (0x%x ctx %d) at 0x%x\n",
+			  ring->name,
+			  inside ? "inside" : "flushing",
+			  request->batch_obj ?
+			  request->batch_obj->gtt_offset : 0,
+			  request->ctx ? request->ctx->id : 0,
+			  acthd);
+
+		guilty = true;
+	}
+
+	/* If contexts are disabled or this is the default context, use
+	 * file_priv->reset_state
+	 */
+	if (request->ctx && request->ctx->id != DEFAULT_CONTEXT_ID)
+		hs = &request->ctx->hang_stats;
+	else if (request->file_priv)
+		hs = &request->file_priv->hang_stats;
+
+	if (hs) {
+		if (guilty)
+			hs->batch_active++;
+		else
+			hs->batch_pending++;
+	}
+}
+
+static void i915_gem_free_request(struct drm_i915_gem_request *request)
+{
+	list_del(&request->list);
+	i915_gem_request_remove_from_client(request);
+
+	if (request->ctx)
+		i915_gem_context_unreference(request->ctx);
+
+	kfree(request);
+}
+
 static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
 				      struct intel_ring_buffer *ring)
 {
+	u32 completed_seqno;
+	u32 acthd;
+
+	acthd = intel_ring_get_active_head(ring);
+	completed_seqno = ring->get_seqno(ring, false);
+
 	while (!list_empty(&ring->request_list)) {
 		struct drm_i915_gem_request *request;
 
@@ -2110,9 +2230,10 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
 					   struct drm_i915_gem_request,
 					   list);
 
-		list_del(&request->list);
-		i915_gem_request_remove_from_client(request);
-		kfree(request);
+		if (request->seqno > completed_seqno)
+			i915_set_reset_status(ring, request, acthd);
+
+		i915_gem_free_request(request);
 	}
 
 	while (!list_empty(&ring->active_list)) {
@@ -2193,9 +2314,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 		 */
 		ring->last_retired_head = request->tail;
 
-		list_del(&request->list);
-		i915_gem_request_remove_from_client(request);
-		kfree(request);
+		i915_gem_free_request(request);
 	}
 
 	/* Move any buffers on the active list that are no longer referenced
@@ -2262,7 +2381,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	idle = true;
 	for_each_ring(ring, dev_priv, i) {
 		if (ring->gpu_caches_dirty)
-			i915_add_request(ring, NULL, NULL);
+			i915_add_request(ring, NULL);
 
 		idle &= list_empty(&ring->request_list);
 	}
@@ -2494,9 +2613,10 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 		obj->has_aliasing_ppgtt_mapping = 0;
 	}
 	i915_gem_gtt_finish_object(obj);
+	i915_gem_object_unpin_pages(obj);
 
 	list_del(&obj->mm_list);
-	list_move_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
+	list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 	/* Avoid an unnecessary call to unbind on rebind. */
 	obj->map_and_fenceable = true;
 
@@ -2676,18 +2796,33 @@ static inline int fence_number(struct drm_i915_private *dev_priv,
 	return fence - dev_priv->fence_regs;
 }
 
+struct write_fence {
+	struct drm_device *dev;
+	struct drm_i915_gem_object *obj;
+	int fence;
+};
+
 static void i915_gem_write_fence__ipi(void *data)
 {
+	struct write_fence *args = data;
+
+	/* Required for SNB+ with LLC */
 	wbinvd();
+
+	/* Required for VLV */
+	i915_gem_write_fence(args->dev, args->fence, args->obj);
 }
 
 static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 					 struct drm_i915_fence_reg *fence,
 					 bool enable)
 {
-	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int fence_reg = fence_number(dev_priv, fence);
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	struct write_fence args = {
+		.dev = obj->base.dev,
+		.fence = fence_number(dev_priv, fence),
+		.obj = enable ? obj : NULL,
+	};
 
 	/* In order to fully serialize access to the fenced region and
 	 * the update to the fence register we need to take extreme
@@ -2698,13 +2833,19 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 	 * SNB+ we need to take a step further and emit an explicit wbinvd()
 	 * on each processor in order to manually flush all memory
 	 * transactions before updating the fence register.
+	 *
+	 * However, Valleyview complicates matter. There the wbinvd is
+	 * insufficient and unlike SNB/IVB requires the serialising
+	 * register write. (Note that that register write by itself is
+	 * conversely not sufficient for SNB+.) To compromise, we do both.
 	 */
-	if (HAS_LLC(obj->base.dev))
-		on_each_cpu(i915_gem_write_fence__ipi, NULL, 1);
-	i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL);
+	if (INTEL_INFO(args.dev)->gen >= 6)
+		on_each_cpu(i915_gem_write_fence__ipi, &args, 1);
+	else
+		i915_gem_write_fence(args.dev, args.fence, args.obj);
 
 	if (enable) {
-		obj->fence_reg = fence_reg;
+		obj->fence_reg = args.fence;
 		fence->obj = obj;
 		list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
 	} else {
@@ -2883,7 +3024,7 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
 	struct drm_i915_gem_object *obj;
 	int err = 0;
 
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.gtt_list, global_list) {
 		if (obj->gtt_space == NULL) {
 			printk(KERN_ERR "object found on GTT list with no space reserved\n");
 			err++;
@@ -2930,6 +3071,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 	struct drm_mm_node *node;
 	u32 size, fence_size, fence_alignment, unfenced_alignment;
 	bool mappable, fenceable;
+	size_t gtt_max = map_and_fenceable ?
+		dev_priv->gtt.mappable_end : dev_priv->gtt.total;
 	int ret;
 
 	fence_size = i915_gem_get_gtt_size(dev,
@@ -2956,9 +3099,11 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 	/* If the object is bigger than the entire aperture, reject it early
 	 * before evicting everything in a vain attempt to find space.
 	 */
-	if (obj->base.size >
-	    (map_and_fenceable ? dev_priv->gtt.mappable_end : dev_priv->gtt.total)) {
-		DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+	if (obj->base.size > gtt_max) {
+		DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
+			  obj->base.size,
+			  map_and_fenceable ? "mappable" : "total",
+			  gtt_max);
 		return -E2BIG;
 	}
 
@@ -2974,14 +3119,10 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 		return -ENOMEM;
 	}
 
- search_free:
-	if (map_and_fenceable)
-		ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
-							  size, alignment, obj->cache_level,
-							  0, dev_priv->gtt.mappable_end);
-	else
-		ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
-						 size, alignment, obj->cache_level);
+search_free:
+	ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
+						  size, alignment,
+						  obj->cache_level, 0, gtt_max);
 	if (ret) {
 		ret = i915_gem_evict_something(dev, size, alignment,
 					       obj->cache_level,
@@ -3007,7 +3148,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 		return ret;
 	}
 
-	list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
+	list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
 	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
 	obj->gtt_space = node;
@@ -3022,7 +3163,6 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 
 	obj->map_and_fenceable = mappable && fenceable;
 
-	i915_gem_object_unpin_pages(obj);
 	trace_i915_gem_object_bind(obj, map_and_fenceable);
 	i915_gem_verify_gtt(dev);
 	return 0;
@@ -3722,7 +3862,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			  const struct drm_i915_gem_object_ops *ops)
 {
 	INIT_LIST_HEAD(&obj->mm_list);
-	INIT_LIST_HEAD(&obj->gtt_list);
+	INIT_LIST_HEAD(&obj->global_list);
 	INIT_LIST_HEAD(&obj->ring_list);
 	INIT_LIST_HEAD(&obj->exec_list);
 
@@ -3822,7 +3962,13 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 		dev_priv->mm.interruptible = was_interruptible;
 	}
 
-	obj->pages_pin_count = 0;
+	/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
+	 * before progressing. */
+	if (obj->stolen)
+		i915_gem_object_unpin_pages(obj);
+
+	if (WARN_ON(obj->pages_pin_count))
+		obj->pages_pin_count = 0;
 	i915_gem_object_put_pages(obj);
 	i915_gem_object_free_mmap_offset(obj);
 	i915_gem_object_release_stolen(obj);
@@ -3973,12 +4119,21 @@ static int i915_gem_init_rings(struct drm_device *dev)
 			goto cleanup_bsd_ring;
 	}
 
+	if (HAS_VEBOX(dev)) {
+		ret = intel_init_vebox_ring_buffer(dev);
+		if (ret)
+			goto cleanup_blt_ring;
+	}
+
+
 	ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
 	if (ret)
-		goto cleanup_blt_ring;
+		goto cleanup_vebox_ring;
 
 	return 0;
 
+cleanup_vebox_ring:
+	intel_cleanup_ring_buffer(&dev_priv->ring[VECS]);
 cleanup_blt_ring:
 	intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
 cleanup_bsd_ring:
@@ -4453,10 +4608,10 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 	}
 
 	cnt = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
 		if (obj->pages_pin_count == 0)
 			cnt += obj->base.size >> PAGE_SHIFT;
-	list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list)
 		if (obj->pin_count == 0 && obj->pages_pin_count == 0)
 			cnt += obj->base.size >> PAGE_SHIFT;
 

+ 88 - 30
drivers/gpu/drm/i915/i915_gem_context.c

@@ -113,7 +113,7 @@ static int get_context_size(struct drm_device *dev)
 	case 7:
 		reg = I915_READ(GEN7_CXT_SIZE);
 		if (IS_HASWELL(dev))
-			ret = HSW_CXT_TOTAL_SIZE(reg) * 64;
+			ret = HSW_CXT_TOTAL_SIZE;
 		else
 			ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
 		break;
@@ -124,10 +124,10 @@ static int get_context_size(struct drm_device *dev)
 	return ret;
 }
 
-static void do_destroy(struct i915_hw_context *ctx)
+void i915_gem_context_free(struct kref *ctx_ref)
 {
-	if (ctx->file_priv)
-		idr_remove(&ctx->file_priv->context_idr, ctx->id);
+	struct i915_hw_context *ctx = container_of(ctx_ref,
+						   typeof(*ctx), ref);
 
 	drm_gem_object_unreference(&ctx->obj->base);
 	kfree(ctx);
@@ -145,6 +145,7 @@ create_hw_context(struct drm_device *dev,
 	if (ctx == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	kref_init(&ctx->ref);
 	ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
 	if (ctx->obj == NULL) {
 		kfree(ctx);
@@ -155,7 +156,8 @@ create_hw_context(struct drm_device *dev,
 	if (INTEL_INFO(dev)->gen >= 7) {
 		ret = i915_gem_object_set_cache_level(ctx->obj,
 						      I915_CACHE_LLC_MLC);
-		if (ret)
+		/* Failure shouldn't ever happen this early */
+		if (WARN_ON(ret))
 			goto err_out;
 	}
 
@@ -169,18 +171,18 @@ create_hw_context(struct drm_device *dev,
 	if (file_priv == NULL)
 		return ctx;
 
-	ctx->file_priv = file_priv;
-
 	ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0,
 			GFP_KERNEL);
 	if (ret < 0)
 		goto err_out;
+
+	ctx->file_priv = file_priv;
 	ctx->id = ret;
 
 	return ctx;
 
 err_out:
-	do_destroy(ctx);
+	i915_gem_context_unreference(ctx);
 	return ERR_PTR(ret);
 }
 
@@ -213,12 +215,16 @@ static int create_default_context(struct drm_i915_private *dev_priv)
 	 */
 	dev_priv->ring[RCS].default_context = ctx;
 	ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false, false);
-	if (ret)
+	if (ret) {
+		DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
 		goto err_destroy;
+	}
 
 	ret = do_switch(ctx);
-	if (ret)
+	if (ret) {
+		DRM_DEBUG_DRIVER("Switch failed %d\n", ret);
 		goto err_unpin;
+	}
 
 	DRM_DEBUG_DRIVER("Default HW context loaded\n");
 	return 0;
@@ -226,7 +232,7 @@ static int create_default_context(struct drm_i915_private *dev_priv)
 err_unpin:
 	i915_gem_object_unpin(ctx->obj);
 err_destroy:
-	do_destroy(ctx);
+	i915_gem_context_unreference(ctx);
 	return ret;
 }
 
@@ -236,6 +242,7 @@ void i915_gem_context_init(struct drm_device *dev)
 
 	if (!HAS_HW_CONTEXTS(dev)) {
 		dev_priv->hw_contexts_disabled = true;
+		DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
 		return;
 	}
 
@@ -248,11 +255,13 @@ void i915_gem_context_init(struct drm_device *dev)
 
 	if (dev_priv->hw_context_size > (1<<20)) {
 		dev_priv->hw_contexts_disabled = true;
+		DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
 		return;
 	}
 
 	if (create_default_context(dev_priv)) {
 		dev_priv->hw_contexts_disabled = true;
+		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
 		return;
 	}
 
@@ -262,6 +271,7 @@ void i915_gem_context_init(struct drm_device *dev)
 void i915_gem_context_fini(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 
 	if (dev_priv->hw_contexts_disabled)
 		return;
@@ -271,9 +281,16 @@ void i915_gem_context_fini(struct drm_device *dev)
 	 * other code, leading to spurious errors. */
 	intel_gpu_reset(dev);
 
-	i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj);
+	i915_gem_object_unpin(dctx->obj);
 
-	do_destroy(dev_priv->ring[RCS].default_context);
+	/* When default context is created and switched to, base object refcount
+	 * will be 2 (+1 from object creation and +1 from do_switch()).
+	 * i915_gem_context_fini() will be called after gpu_idle() has switched
+	 * to default context. So we need to unreference the base object once
+	 * to offset the do_switch part, so that i915_gem_context_unreference()
+	 * can then free the base object correctly. */
+	drm_gem_object_unreference(&dctx->obj->base);
+	i915_gem_context_unreference(dctx);
 }
 
 static int context_idr_cleanup(int id, void *p, void *data)
@@ -282,11 +299,38 @@ static int context_idr_cleanup(int id, void *p, void *data)
 
 	BUG_ON(id == DEFAULT_CONTEXT_ID);
 
-	do_destroy(ctx);
-
+	i915_gem_context_unreference(ctx);
 	return 0;
 }
 
+struct i915_ctx_hang_stats *
+i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+				struct drm_file *file,
+				u32 id)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct i915_hw_context *to;
+
+	if (dev_priv->hw_contexts_disabled)
+		return ERR_PTR(-ENOENT);
+
+	if (ring->id != RCS)
+		return ERR_PTR(-EINVAL);
+
+	if (file == NULL)
+		return ERR_PTR(-EINVAL);
+
+	if (id == DEFAULT_CONTEXT_ID)
+		return &file_priv->hang_stats;
+
+	to = i915_gem_context_get(file->driver_priv, id);
+	if (to == NULL)
+		return ERR_PTR(-ENOENT);
+
+	return &to->hang_stats;
+}
+
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv = file->driver_priv;
@@ -325,6 +369,7 @@ mi_set_context(struct intel_ring_buffer *ring,
 	if (ret)
 		return ret;
 
+	/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw */
 	if (IS_GEN7(ring->dev))
 		intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 	else
@@ -353,13 +398,13 @@ mi_set_context(struct intel_ring_buffer *ring,
 static int do_switch(struct i915_hw_context *to)
 {
 	struct intel_ring_buffer *ring = to->ring;
-	struct drm_i915_gem_object *from_obj = ring->last_context_obj;
+	struct i915_hw_context *from = ring->last_context;
 	u32 hw_flags = 0;
 	int ret;
 
-	BUG_ON(from_obj != NULL && from_obj->pin_count == 0);
+	BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0);
 
-	if (from_obj == to->obj)
+	if (from == to)
 		return 0;
 
 	ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false);
@@ -382,7 +427,7 @@ static int do_switch(struct i915_hw_context *to)
 
 	if (!to->is_initialized || is_default_context(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
-	else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */
+	else if (WARN_ON_ONCE(from == to)) /* not yet expected */
 		hw_flags |= MI_FORCE_RESTORE;
 
 	ret = mi_set_context(ring, to, hw_flags);
@@ -397,9 +442,9 @@ static int do_switch(struct i915_hw_context *to)
 	 * is a bit suboptimal because the retiring can occur simply after the
 	 * MI_SET_CONTEXT instead of when the next seqno has completed.
 	 */
-	if (from_obj != NULL) {
-		from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
-		i915_gem_object_move_to_active(from_obj, ring);
+	if (from != NULL) {
+		from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+		i915_gem_object_move_to_active(from->obj, ring);
 		/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
 		 * whole damn pipeline, we don't need to explicitly mark the
 		 * object dirty. The only exception is that the context must be
@@ -407,15 +452,26 @@ static int do_switch(struct i915_hw_context *to)
 		 * able to defer doing this until we know the object would be
 		 * swapped, but there is no way to do that yet.
 		 */
-		from_obj->dirty = 1;
-		BUG_ON(from_obj->ring != ring);
-		i915_gem_object_unpin(from_obj);
+		from->obj->dirty = 1;
+		BUG_ON(from->obj->ring != ring);
+
+		ret = i915_add_request(ring, NULL);
+		if (ret) {
+			/* Too late, we've already scheduled a context switch.
+			 * Try to undo the change so that the hw state is
+			 * consistent with out tracking. In case of emergency,
+			 * scream.
+			 */
+			WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT));
+			return ret;
+		}
 
-		drm_gem_object_unreference(&from_obj->base);
+		i915_gem_object_unpin(from->obj);
+		i915_gem_context_unreference(from);
 	}
 
-	drm_gem_object_reference(&to->obj->base);
-	ring->last_context_obj = to->obj;
+	i915_gem_context_reference(to);
+	ring->last_context = to;
 	to->is_initialized = true;
 
 	return 0;
@@ -444,6 +500,8 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 	if (dev_priv->hw_contexts_disabled)
 		return 0;
 
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+
 	if (ring != &dev_priv->ring[RCS])
 		return 0;
 
@@ -512,8 +570,8 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
 		return -ENOENT;
 	}
 
-	do_destroy(ctx);
-
+	idr_remove(&ctx->file_priv->context_idr, ctx->id);
+	i915_gem_context_unreference(ctx);
 	mutex_unlock(&dev->struct_mutex);
 
 	DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);

+ 14 - 4
drivers/gpu/drm/i915/i915_gem_execbuffer.c

@@ -786,7 +786,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 			obj->dirty = 1;
 			obj->last_write_seqno = intel_ring_get_seqno(ring);
 			if (obj->pin_count) /* check for potential scanout */
-				intel_mark_fb_busy(obj);
+				intel_mark_fb_busy(obj, ring);
 		}
 
 		trace_i915_gem_object_change_domain(obj, old_read, old_write);
@@ -796,13 +796,14 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 static void
 i915_gem_execbuffer_retire_commands(struct drm_device *dev,
 				    struct drm_file *file,
-				    struct intel_ring_buffer *ring)
+				    struct intel_ring_buffer *ring,
+				    struct drm_i915_gem_object *obj)
 {
 	/* Unconditionally force add_request to emit a full flush. */
 	ring->gpu_caches_dirty = true;
 
 	/* Add a breadcrumb for the completion of the batch buffer */
-	(void)i915_add_request(ring, file, NULL);
+	(void)__i915_add_request(ring, file, obj, NULL);
 }
 
 static int
@@ -885,6 +886,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			return -EPERM;
 		}
 		break;
+	case I915_EXEC_VEBOX:
+		ring = &dev_priv->ring[VECS];
+		if (ctx_id != 0) {
+			DRM_DEBUG("Ring %s doesn't support contexts\n",
+				  ring->name);
+			return -EPERM;
+		}
+		break;
+
 	default:
 		DRM_DEBUG("execbuf with unknown ring: %d\n",
 			  (int)(args->flags & I915_EXEC_RING_MASK));
@@ -1074,7 +1084,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
 
 	i915_gem_execbuffer_move_to_active(&eb->objects, ring);
-	i915_gem_execbuffer_retire_commands(dev, file, ring);
+	i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
 
 err:
 	eb_destroy(eb);

+ 83 - 31
drivers/gpu/drm/i915/i915_gem_gtt.c

@@ -28,8 +28,6 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
-typedef uint32_t gen6_gtt_pte_t;
-
 /* PPGTT stuff */
 #define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
 
@@ -44,29 +42,22 @@ typedef uint32_t gen6_gtt_pte_t;
 #define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)
 #define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
 
-static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
-					     dma_addr_t addr,
-					     enum i915_cache_level level)
+static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
+				      dma_addr_t addr,
+				      enum i915_cache_level level)
 {
 	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
 	case I915_CACHE_LLC_MLC:
-		/* Haswell doesn't set L3 this way */
-		if (IS_HASWELL(dev))
-			pte |= GEN6_PTE_CACHE_LLC;
-		else
-			pte |= GEN6_PTE_CACHE_LLC_MLC;
+		pte |= GEN6_PTE_CACHE_LLC_MLC;
 		break;
 	case I915_CACHE_LLC:
 		pte |= GEN6_PTE_CACHE_LLC;
 		break;
 	case I915_CACHE_NONE:
-		if (IS_HASWELL(dev))
-			pte |= HSW_PTE_UNCACHED;
-		else
-			pte |= GEN6_PTE_UNCACHED;
+		pte |= GEN6_PTE_UNCACHED;
 		break;
 	default:
 		BUG();
@@ -75,16 +66,48 @@ static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
 	return pte;
 }
 
-static int gen6_ppgtt_enable(struct drm_device *dev)
+#define BYT_PTE_WRITEABLE		(1 << 1)
+#define BYT_PTE_SNOOPED_BY_CPU_CACHES	(1 << 2)
+
+static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
+				     dma_addr_t addr,
+				     enum i915_cache_level level)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t pd_offset;
-	struct intel_ring_buffer *ring;
-	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+	/* Mark the page as writeable.  Other platforms don't have a
+	 * setting for read-only/writable, so this matches that behavior.
+	 */
+	pte |= BYT_PTE_WRITEABLE;
+
+	if (level != I915_CACHE_NONE)
+		pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
+
+	return pte;
+}
+
+static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
+				     dma_addr_t addr,
+				     enum i915_cache_level level)
+{
+	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+	if (level != I915_CACHE_NONE)
+		pte |= GEN6_PTE_CACHE_LLC;
+
+	return pte;
+}
+
+static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
+{
+	struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
 	gen6_gtt_pte_t __iomem *pd_addr;
 	uint32_t pd_entry;
 	int i;
 
+	WARN_ON(ppgtt->pd_offset & 0x3f);
 	pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
 		ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
 	for (i = 0; i < ppgtt->num_pd_entries; i++) {
@@ -97,6 +120,19 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
 		writel(pd_entry, pd_addr + i);
 	}
 	readl(pd_addr);
+}
+
+static int gen6_ppgtt_enable(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t pd_offset;
+	struct intel_ring_buffer *ring;
+	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+	int i;
+
+	BUG_ON(ppgtt->pd_offset & 0x3f);
+
+	gen6_write_pdes(ppgtt);
 
 	pd_offset = ppgtt->pd_offset;
 	pd_offset /= 64; /* in cachelines, */
@@ -154,9 +190,9 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
-	scratch_pte = gen6_pte_encode(ppgtt->dev,
-				      ppgtt->scratch_page_dma_addr,
-				      I915_CACHE_LLC);
+	scratch_pte = ppgtt->pte_encode(ppgtt->dev,
+					ppgtt->scratch_page_dma_addr,
+					I915_CACHE_LLC);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -191,8 +227,8 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
 		dma_addr_t page_addr;
 
 		page_addr = sg_page_iter_dma_address(&sg_iter);
-		pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr,
-						    cache_level);
+		pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
+						      cache_level);
 		if (++act_pte == I915_PPGTT_PT_ENTRIES) {
 			kunmap_atomic(pt_vaddr);
 			act_pt++;
@@ -233,8 +269,15 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 	/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
 	 * entries. For aliasing ppgtt support we just steal them at the end for
 	 * now. */
-       first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
+	first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
 
+	if (IS_HASWELL(dev)) {
+		ppgtt->pte_encode = hsw_pte_encode;
+	} else if (IS_VALLEYVIEW(dev)) {
+		ppgtt->pte_encode = byt_pte_encode;
+	} else {
+		ppgtt->pte_encode = gen6_pte_encode;
+	}
 	ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
 	ppgtt->enable = gen6_ppgtt_enable;
 	ppgtt->clear_range = gen6_ppgtt_clear_range;
@@ -396,7 +439,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 	dev_priv->gtt.gtt_clear_range(dev, dev_priv->gtt.start / PAGE_SIZE,
 				      dev_priv->gtt.total / PAGE_SIZE);
 
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		i915_gem_clflush_object(obj);
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 	}
@@ -437,7 +480,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_page_iter_dma_address(&sg_iter);
-		iowrite32(gen6_pte_encode(dev, addr, level), &gtt_entries[i]);
+		iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
+			  &gtt_entries[i]);
 		i++;
 	}
 
@@ -449,7 +493,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
 	 */
 	if (i != 0)
 		WARN_ON(readl(&gtt_entries[i-1])
-			!= gen6_pte_encode(dev, addr, level));
+			!= dev_priv->gtt.pte_encode(dev, addr, level));
 
 	/* This next bit makes the above posting read even more important. We
 	 * want to flush the TLBs only after we're certain all the PTE updates
@@ -474,8 +518,9 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
 		 first_entry, num_entries, max_entries))
 		num_entries = max_entries;
 
-	scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma,
-				      I915_CACHE_LLC);
+	scratch_pte = dev_priv->gtt.pte_encode(dev,
+					       dev_priv->gtt.scratch_page_dma,
+					       I915_CACHE_LLC);
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
 	readl(gtt_base);
@@ -586,7 +631,7 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
 		dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
 
 	/* Mark any preallocated objects as occupied */
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
 			      obj->gtt_offset, obj->base.size);
 
@@ -809,6 +854,13 @@ int i915_gem_gtt_init(struct drm_device *dev)
 	} else {
 		dev_priv->gtt.gtt_probe = gen6_gmch_probe;
 		dev_priv->gtt.gtt_remove = gen6_gmch_remove;
+		if (IS_HASWELL(dev)) {
+			dev_priv->gtt.pte_encode = hsw_pte_encode;
+		} else if (IS_VALLEYVIEW(dev)) {
+			dev_priv->gtt.pte_encode = byt_pte_encode;
+		} else {
+			dev_priv->gtt.pte_encode = gen6_pte_encode;
+		}
 	}
 
 	ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,

+ 23 - 8
drivers/gpu/drm/i915/i915_gem_stolen.c

@@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 	 * its value of TOLUD.
 	 */
 	base = 0;
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (IS_VALLEYVIEW(dev)) {
+		pci_read_config_dword(dev->pdev, 0x5c, &base);
+		base &= ~((1<<20) - 1);
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		/* Read Base Data of Stolen Memory Register (BDSM) directly.
 		 * Note that there is also a MCHBAR miror at 0x1080c0 or
 		 * we could use device 2:0x5c instead.
@@ -136,6 +139,7 @@ static int i915_setup_compression(struct drm_device *dev, int size)
 err_fb:
 	drm_mm_put_block(compressed_fb);
 err:
+	pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
 	return -ENOSPC;
 }
 
@@ -143,7 +147,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->mm.stolen_base == 0)
+	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return -ENODEV;
 
 	if (size < dev_priv->cfb_size)
@@ -175,6 +179,9 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	if (!drm_mm_initialized(&dev_priv->mm.stolen))
+		return;
+
 	i915_gem_stolen_cleanup_compression(dev);
 	drm_mm_takedown(&dev_priv->mm.stolen);
 }
@@ -182,6 +189,7 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
 int i915_gem_init_stolen(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int bios_reserved = 0;
 
 	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
 	if (dev_priv->mm.stolen_base == 0)
@@ -190,8 +198,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
 	DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
 		      dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
 
+	if (IS_VALLEYVIEW(dev))
+		bios_reserved = 1024*1024; /* top 1M on VLV/BYT */
+
 	/* Basic memrange allocator for stolen space */
-	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size);
+	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
+		    bios_reserved);
 
 	return 0;
 }
@@ -270,7 +282,7 @@ _i915_gem_object_create_stolen(struct drm_device *dev,
 		goto cleanup;
 
 	obj->has_dma_mapping = true;
-	obj->pages_pin_count = 1;
+	i915_gem_object_pin_pages(obj);
 	obj->stolen = stolen;
 
 	obj->base.write_domain = I915_GEM_DOMAIN_GTT;
@@ -291,7 +303,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
 	struct drm_i915_gem_object *obj;
 	struct drm_mm_node *stolen;
 
-	if (dev_priv->mm.stolen_base == 0)
+	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return NULL;
 
 	DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
@@ -322,7 +334,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 	struct drm_i915_gem_object *obj;
 	struct drm_mm_node *stolen;
 
-	if (dev_priv->mm.stolen_base == 0)
+	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return NULL;
 
 	DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%x, gtt_offset=%x, size=%x\n",
@@ -330,7 +342,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 
 	/* KISS and expect everything to be page-aligned */
 	BUG_ON(stolen_offset & 4095);
-	BUG_ON(gtt_offset & 4095);
 	BUG_ON(size & 4095);
 
 	if (WARN_ON(size == 0))
@@ -351,6 +362,10 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 		return NULL;
 	}
 
+	/* Some objects just need physical mem from stolen space */
+	if (gtt_offset == -1)
+		return obj;
+
 	/* To simplify the initialisation sequence between KMS and GTT,
 	 * we allow construction of the stolen object prior to
 	 * setting up the GTT space. The actual reservation will occur
@@ -371,7 +386,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 	obj->gtt_offset = gtt_offset;
 	obj->has_global_gtt_mapping = 1;
 
-	list_add_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
+	list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
 	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
 	return obj;

File diff suppressed because it is too large
+ 662 - 194
drivers/gpu/drm/i915/i915_irq.c


File diff suppressed because it is too large
+ 432 - 245
drivers/gpu/drm/i915/i915_reg.h


+ 10 - 0
drivers/gpu/drm/i915/i915_suspend.c

@@ -192,6 +192,7 @@ static void i915_restore_vga(struct drm_device *dev)
 static void i915_save_display(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
 	/* Display arbitration control */
 	if (INTEL_INFO(dev)->gen <= 4)
@@ -202,6 +203,8 @@ static void i915_save_display(struct drm_device *dev)
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_save_display_reg(dev);
 
+	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+
 	/* LVDS state */
 	if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
@@ -222,6 +225,8 @@ static void i915_save_display(struct drm_device *dev)
 			dev_priv->regfile.saveLVDS = I915_READ(LVDS);
 	}
 
+	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+
 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
 		dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
@@ -257,6 +262,7 @@ static void i915_restore_display(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 mask = 0xffffffff;
+	unsigned long flags;
 
 	/* Display arbitration */
 	if (INTEL_INFO(dev)->gen <= 4)
@@ -265,6 +271,8 @@ static void i915_restore_display(struct drm_device *dev)
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_restore_display_reg(dev);
 
+	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+
 	/* LVDS state */
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
 		I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
@@ -304,6 +312,8 @@ static void i915_restore_display(struct drm_device *dev)
 		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
 	}
 
+	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+
 	/* only restore FBC info on the platform that supports FBC*/
 	intel_disable_fbc(dev);
 	if (I915_HAS_FBC(dev)) {

+ 55 - 19
drivers/gpu/drm/i915/i915_sysfs.c

@@ -212,7 +212,13 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 	int ret;
 
 	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
+	if (IS_VALLEYVIEW(dev_priv->dev)) {
+		u32 freq;
+		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+		ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
+	} else {
+		ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
+	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -226,7 +232,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 	int ret;
 
 	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
+	if (IS_VALLEYVIEW(dev_priv->dev))
+		ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
+	else
+		ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -246,16 +255,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	val /= GT_FREQUENCY_MULTIPLIER;
-
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-	hw_max = dev_priv->rps.hw_max;
-	non_oc_max = (rp_state_cap & 0xff);
-	hw_min = ((rp_state_cap & 0xff0000) >> 16);
+	if (IS_VALLEYVIEW(dev_priv->dev)) {
+		val = vlv_freq_opcode(dev_priv->mem_freq, val);
+
+		hw_max = valleyview_rps_max_freq(dev_priv);
+		hw_min = valleyview_rps_min_freq(dev_priv);
+		non_oc_max = hw_max;
+	} else {
+		val /= GT_FREQUENCY_MULTIPLIER;
+
+		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		hw_max = dev_priv->rps.hw_max;
+		non_oc_max = (rp_state_cap & 0xff);
+		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+	}
 
-	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
+	if (val < hw_min || val > hw_max ||
+	    val < dev_priv->rps.min_delay) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
@@ -264,8 +282,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 		DRM_DEBUG("User requested overclocking to %d\n",
 			  val * GT_FREQUENCY_MULTIPLIER);
 
-	if (dev_priv->rps.cur_delay > val)
-		gen6_set_rps(dev_priv->dev, val);
+	if (dev_priv->rps.cur_delay > val) {
+		if (IS_VALLEYVIEW(dev_priv->dev))
+			valleyview_set_rps(dev_priv->dev, val);
+		else
+			gen6_set_rps(dev_priv->dev, val);
+	}
 
 	dev_priv->rps.max_delay = val;
 
@@ -282,7 +304,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 	int ret;
 
 	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
+	if (IS_VALLEYVIEW(dev_priv->dev))
+		ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
+	else
+		ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
@@ -302,21 +327,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	val /= GT_FREQUENCY_MULTIPLIER;
-
 	mutex_lock(&dev_priv->rps.hw_lock);
 
-	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-	hw_max = dev_priv->rps.hw_max;
-	hw_min = ((rp_state_cap & 0xff0000) >> 16);
+	if (IS_VALLEYVIEW(dev)) {
+		val = vlv_freq_opcode(dev_priv->mem_freq, val);
+
+		hw_max = valleyview_rps_max_freq(dev_priv);
+		hw_min = valleyview_rps_min_freq(dev_priv);
+	} else {
+		val /= GT_FREQUENCY_MULTIPLIER;
+
+		rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		hw_max = dev_priv->rps.hw_max;
+		hw_min = ((rp_state_cap & 0xff0000) >> 16);
+	}
 
 	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
-	if (dev_priv->rps.cur_delay < val)
-		gen6_set_rps(dev_priv->dev, val);
+	if (dev_priv->rps.cur_delay < val) {
+		if (IS_VALLEYVIEW(dev))
+			valleyview_set_rps(dev, val);
+		else
+			gen6_set_rps(dev_priv->dev, val);
+	}
 
 	dev_priv->rps.min_delay = val;
 

+ 45 - 45
drivers/gpu/drm/i915/i915_ums.c

@@ -41,7 +41,7 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 		return false;
 
 	if (HAS_PCH_SPLIT(dev))
-		dpll_reg = _PCH_DPLL(pipe);
+		dpll_reg = PCH_DPLL(pipe);
 	else
 		dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
 
@@ -148,13 +148,13 @@ void i915_save_display_reg(struct drm_device *dev)
 		dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
 		dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
 
-		dev_priv->regfile.saveTRANSACONF = I915_READ(_TRANSACONF);
-		dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
-		dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
-		dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
-		dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
-		dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
-		dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
+		dev_priv->regfile.saveTRANSACONF = I915_READ(_PCH_TRANSACONF);
+		dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_PCH_TRANS_HTOTAL_A);
+		dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_PCH_TRANS_HBLANK_A);
+		dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_PCH_TRANS_HSYNC_A);
+		dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_PCH_TRANS_VTOTAL_A);
+		dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_PCH_TRANS_VBLANK_A);
+		dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_PCH_TRANS_VSYNC_A);
 	}
 
 	dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR);
@@ -205,13 +205,13 @@ void i915_save_display_reg(struct drm_device *dev)
 		dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
 		dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
 
-		dev_priv->regfile.saveTRANSBCONF = I915_READ(_TRANSBCONF);
-		dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
-		dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
-		dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
-		dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
-		dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
-		dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
+		dev_priv->regfile.saveTRANSBCONF = I915_READ(_PCH_TRANSBCONF);
+		dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_PCH_TRANS_HTOTAL_B);
+		dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_PCH_TRANS_HBLANK_B);
+		dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_PCH_TRANS_HSYNC_B);
+		dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_PCH_TRANS_VTOTAL_B);
+		dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_PCH_TRANS_VBLANK_B);
+		dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_PCH_TRANS_VSYNC_B);
 	}
 
 	dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR);
@@ -259,14 +259,14 @@ void i915_save_display_reg(struct drm_device *dev)
 		dev_priv->regfile.saveDP_B = I915_READ(DP_B);
 		dev_priv->regfile.saveDP_C = I915_READ(DP_C);
 		dev_priv->regfile.saveDP_D = I915_READ(DP_D);
-		dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
-		dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
-		dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
-		dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
-		dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
-		dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
-		dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
-		dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
+		dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_DATA_M_G4X);
+		dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_DATA_M_G4X);
+		dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_DATA_N_G4X);
+		dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_DATA_N_G4X);
+		dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_LINK_M_G4X);
+		dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_LINK_M_G4X);
+		dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_LINK_N_G4X);
+		dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_LINK_N_G4X);
 	}
 	/* FIXME: regfile.save TV & SDVO state */
 
@@ -282,14 +282,14 @@ void i915_restore_display_reg(struct drm_device *dev)
 
 	/* Display port ratios (must be done before clock is set) */
 	if (SUPPORTS_INTEGRATED_DP(dev)) {
-		I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
-		I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
-		I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
-		I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
-		I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->regfile.savePIPEA_DP_LINK_M);
-		I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->regfile.savePIPEB_DP_LINK_M);
-		I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->regfile.savePIPEA_DP_LINK_N);
-		I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->regfile.savePIPEB_DP_LINK_N);
+		I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
+		I915_WRITE(_PIPEB_DATA_M_G4X, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
+		I915_WRITE(_PIPEA_DATA_N_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
+		I915_WRITE(_PIPEB_DATA_N_G4X, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
+		I915_WRITE(_PIPEA_LINK_M_G4X, dev_priv->regfile.savePIPEA_DP_LINK_M);
+		I915_WRITE(_PIPEB_LINK_M_G4X, dev_priv->regfile.savePIPEB_DP_LINK_M);
+		I915_WRITE(_PIPEA_LINK_N_G4X, dev_priv->regfile.savePIPEA_DP_LINK_N);
+		I915_WRITE(_PIPEB_LINK_N_G4X, dev_priv->regfile.savePIPEB_DP_LINK_N);
 	}
 
 	/* Fences */
@@ -379,13 +379,13 @@ void i915_restore_display_reg(struct drm_device *dev)
 		I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ);
 		I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS);
 
-		I915_WRITE(_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
-		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
-		I915_WRITE(_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
-		I915_WRITE(_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
-		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
-		I915_WRITE(_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
-		I915_WRITE(_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
+		I915_WRITE(_PCH_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
+		I915_WRITE(_PCH_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
+		I915_WRITE(_PCH_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
+		I915_WRITE(_PCH_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
+		I915_WRITE(_PCH_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
+		I915_WRITE(_PCH_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
+		I915_WRITE(_PCH_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
 	}
 
 	/* Restore plane info */
@@ -448,13 +448,13 @@ void i915_restore_display_reg(struct drm_device *dev)
 		I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ);
 		I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS);
 
-		I915_WRITE(_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
-		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
-		I915_WRITE(_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
-		I915_WRITE(_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
-		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
-		I915_WRITE(_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
-		I915_WRITE(_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
+		I915_WRITE(_PCH_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
+		I915_WRITE(_PCH_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
+		I915_WRITE(_PCH_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
+		I915_WRITE(_PCH_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
+		I915_WRITE(_PCH_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
+		I915_WRITE(_PCH_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
+		I915_WRITE(_PCH_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
 	}
 
 	/* Restore plane info */

+ 50 - 50
drivers/gpu/drm/i915/intel_bios.c

@@ -212,7 +212,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 	if (!lvds_options)
 		return;
 
-	dev_priv->lvds_dither = lvds_options->pixel_dither;
+	dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
 	if (lvds_options->panel_type == 0xff)
 		return;
 
@@ -226,7 +226,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 	if (!lvds_lfp_data_ptrs)
 		return;
 
-	dev_priv->lvds_vbt = 1;
+	dev_priv->vbt.lvds_vbt = 1;
 
 	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
 					       lvds_lfp_data_ptrs,
@@ -238,7 +238,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 
 	fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
 
-	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
+	dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 
 	DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
 	drm_mode_debug_printmodeline(panel_fixed_mode);
@@ -274,9 +274,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 		/* check the resolution, just to be sure */
 		if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
 		    fp_timing->y_res == panel_fixed_mode->vdisplay) {
-			dev_priv->bios_lvds_val = fp_timing->lvds_reg_val;
+			dev_priv->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
 			DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
-				      dev_priv->bios_lvds_val);
+				      dev_priv->vbt.bios_lvds_val);
 		}
 	}
 }
@@ -316,7 +316,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 
 	fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
 
-	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
+	dev_priv->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
 
 	DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
 	drm_mode_debug_printmodeline(panel_fixed_mode);
@@ -345,20 +345,20 @@ parse_general_features(struct drm_i915_private *dev_priv,
 
 	general = find_section(bdb, BDB_GENERAL_FEATURES);
 	if (general) {
-		dev_priv->int_tv_support = general->int_tv_support;
-		dev_priv->int_crt_support = general->int_crt_support;
-		dev_priv->lvds_use_ssc = general->enable_ssc;
-		dev_priv->lvds_ssc_freq =
+		dev_priv->vbt.int_tv_support = general->int_tv_support;
+		dev_priv->vbt.int_crt_support = general->int_crt_support;
+		dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
+		dev_priv->vbt.lvds_ssc_freq =
 			intel_bios_ssc_frequency(dev, general->ssc_freq);
-		dev_priv->display_clock_mode = general->display_clock_mode;
-		dev_priv->fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
+		dev_priv->vbt.display_clock_mode = general->display_clock_mode;
+		dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
 		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
-			      dev_priv->int_tv_support,
-			      dev_priv->int_crt_support,
-			      dev_priv->lvds_use_ssc,
-			      dev_priv->lvds_ssc_freq,
-			      dev_priv->display_clock_mode,
-			      dev_priv->fdi_rx_polarity_inverted);
+			      dev_priv->vbt.int_tv_support,
+			      dev_priv->vbt.int_crt_support,
+			      dev_priv->vbt.lvds_use_ssc,
+			      dev_priv->vbt.lvds_ssc_freq,
+			      dev_priv->vbt.display_clock_mode,
+			      dev_priv->vbt.fdi_rx_polarity_inverted);
 	}
 }
 
@@ -375,7 +375,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
 			int bus_pin = general->crt_ddc_gmbus_pin;
 			DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
 			if (intel_gmbus_is_port_valid(bus_pin))
-				dev_priv->crt_ddc_pin = bus_pin;
+				dev_priv->vbt.crt_ddc_pin = bus_pin;
 		} else {
 			DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
 				      block_size);
@@ -486,7 +486,7 @@ parse_driver_features(struct drm_i915_private *dev_priv,
 
 	if (SUPPORTS_EDP(dev) &&
 	    driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
-		dev_priv->edp.support = 1;
+		dev_priv->vbt.edp_support = 1;
 
 	if (driver->dual_frequency)
 		dev_priv->render_reclock_avail = true;
@@ -501,20 +501,20 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 
 	edp = find_section(bdb, BDB_EDP);
 	if (!edp) {
-		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support)
+		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support)
 			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
 		return;
 	}
 
 	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
 	case EDP_18BPP:
-		dev_priv->edp.bpp = 18;
+		dev_priv->vbt.edp_bpp = 18;
 		break;
 	case EDP_24BPP:
-		dev_priv->edp.bpp = 24;
+		dev_priv->vbt.edp_bpp = 24;
 		break;
 	case EDP_30BPP:
-		dev_priv->edp.bpp = 30;
+		dev_priv->vbt.edp_bpp = 30;
 		break;
 	}
 
@@ -522,48 +522,48 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 	edp_pps = &edp->power_seqs[panel_type];
 	edp_link_params = &edp->link_params[panel_type];
 
-	dev_priv->edp.pps = *edp_pps;
+	dev_priv->vbt.edp_pps = *edp_pps;
 
-	dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
+	dev_priv->vbt.edp_rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
 		DP_LINK_BW_1_62;
 	switch (edp_link_params->lanes) {
 	case 0:
-		dev_priv->edp.lanes = 1;
+		dev_priv->vbt.edp_lanes = 1;
 		break;
 	case 1:
-		dev_priv->edp.lanes = 2;
+		dev_priv->vbt.edp_lanes = 2;
 		break;
 	case 3:
 	default:
-		dev_priv->edp.lanes = 4;
+		dev_priv->vbt.edp_lanes = 4;
 		break;
 	}
 	switch (edp_link_params->preemphasis) {
 	case 0:
-		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
+		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
 		break;
 	case 1:
-		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
+		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
 		break;
 	case 2:
-		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
+		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
 		break;
 	case 3:
-		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
+		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
 		break;
 	}
 	switch (edp_link_params->vswing) {
 	case 0:
-		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400;
+		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_400;
 		break;
 	case 1:
-		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600;
+		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_600;
 		break;
 	case 2:
-		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800;
+		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_800;
 		break;
 	case 3:
-		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200;
+		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_1200;
 		break;
 	}
 }
@@ -611,13 +611,13 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
 		DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
 		return;
 	}
-	dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
-	if (!dev_priv->child_dev) {
+	dev_priv->vbt.child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
+	if (!dev_priv->vbt.child_dev) {
 		DRM_DEBUG_KMS("No memory space for child device\n");
 		return;
 	}
 
-	dev_priv->child_dev_num = count;
+	dev_priv->vbt.child_dev_num = count;
 	count = 0;
 	for (i = 0; i < child_device_num; i++) {
 		p_child = &(p_defs->devices[i]);
@@ -625,7 +625,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
 			/* skip the device block if device type is invalid */
 			continue;
 		}
-		child_dev_ptr = dev_priv->child_dev + count;
+		child_dev_ptr = dev_priv->vbt.child_dev + count;
 		count++;
 		memcpy((void *)child_dev_ptr, (void *)p_child,
 					sizeof(*p_child));
@@ -638,23 +638,23 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 
-	dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
+	dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
 
 	/* LFP panel data */
-	dev_priv->lvds_dither = 1;
-	dev_priv->lvds_vbt = 0;
+	dev_priv->vbt.lvds_dither = 1;
+	dev_priv->vbt.lvds_vbt = 0;
 
 	/* SDVO panel data */
-	dev_priv->sdvo_lvds_vbt_mode = NULL;
+	dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
 
 	/* general features */
-	dev_priv->int_tv_support = 1;
-	dev_priv->int_crt_support = 1;
+	dev_priv->vbt.int_tv_support = 1;
+	dev_priv->vbt.int_crt_support = 1;
 
 	/* Default to using SSC */
-	dev_priv->lvds_use_ssc = 1;
-	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
-	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
+	dev_priv->vbt.lvds_use_ssc = 1;
+	dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
+	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
 }
 
 static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)

+ 32 - 3
drivers/gpu/drm/i915/intel_crt.c

@@ -84,6 +84,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_crt_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(crt->adpa_reg);
+
+	if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -127,7 +149,7 @@ static void intel_enable_crt(struct intel_encoder *encoder)
 	intel_crt_set_dpms(encoder, crt->connector->base.dpms);
 }
 
-
+/* Special dpms function to support cloning between dvo/sdvo/crt. */
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
 	struct drm_device *dev = connector->dev;
@@ -158,6 +180,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
 	else
 		encoder->connectors_active = true;
 
+	/* We call connector dpms manually below in case pipe dpms doesn't
+	 * change due to cloning. */
 	if (mode < old_dpms) {
 		/* From off to on, enable the pipe first. */
 		intel_crtc_update_dpms(crtc);
@@ -207,6 +231,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
 	if (HAS_PCH_SPLIT(dev))
 		pipe_config->has_pch_encoder = true;
 
+	/* LPT FDI RX only supports 8bpc. */
+	if (HAS_PCH_LPT(dev))
+		pipe_config->pipe_bpp = 24;
+
 	return true;
 }
 
@@ -431,7 +459,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
 
 	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
 
-	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
 	edid = intel_crt_get_edid(connector, i2c);
 
 	if (edid) {
@@ -637,7 +665,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
 	int ret;
 	struct i2c_adapter *i2c;
 
-	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
 	ret = intel_crt_ddc_get_modes(connector, i2c);
 	if (ret || !IS_G4X(dev))
 		return ret;
@@ -774,6 +802,7 @@ void intel_crt_init(struct drm_device *dev)
 	crt->base.compute_config = intel_crt_compute_config;
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
+	crt->base.get_config = intel_crt_get_config;
 	if (I915_HAS_HOTPLUG(dev))
 		crt->base.hpd_pin = HPD_CRT;
 	if (HAS_DDI(dev))

+ 285 - 469
drivers/gpu/drm/i915/intel_ddi.c

@@ -174,6 +174,8 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	 * mode set "sequence for CRT port" document:
 	 * - TP1 to TP2 time with the default value
 	 * - FDI delay to 90h
+	 *
+	 * WaFDIAutoLinkSetTimingOverrride:hsw
 	 */
 	I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
 				  FDI_RX_PWRDN_LANE0_VAL(2) |
@@ -181,7 +183,8 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 
 	/* Enable the PCH Receiver FDI PLL */
 	rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
-		     FDI_RX_PLL_ENABLE | ((intel_crtc->fdi_lanes - 1) << 19);
+		     FDI_RX_PLL_ENABLE |
+		     FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
 	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
 	POSTING_READ(_FDI_RXA_CTL);
 	udelay(220);
@@ -209,7 +212,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 		 * port reversal bit */
 		I915_WRITE(DDI_BUF_CTL(PORT_E),
 			   DDI_BUF_CTL_ENABLE |
-			   ((intel_crtc->fdi_lanes - 1) << 1) |
+			   ((intel_crtc->config.fdi_lanes - 1) << 1) |
 			   hsw_ddi_buf_ctl_values[i / 2]);
 		POSTING_READ(DDI_BUF_CTL(PORT_E));
 
@@ -278,392 +281,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	DRM_ERROR("FDI link training failed!\n");
 }
 
-/* WRPLL clock dividers */
-struct wrpll_tmds_clock {
-	u32 clock;
-	u16 p;		/* Post divider */
-	u16 n2;		/* Feedback divider */
-	u16 r2;		/* Reference divider */
-};
-
-/* Table of matching values for WRPLL clocks programming for each frequency.
- * The code assumes this table is sorted. */
-static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
-	{19750,	38,	25,	18},
-	{20000,	48,	32,	18},
-	{21000,	36,	21,	15},
-	{21912,	42,	29,	17},
-	{22000,	36,	22,	15},
-	{23000,	36,	23,	15},
-	{23500,	40,	40,	23},
-	{23750,	26,	16,	14},
-	{24000,	36,	24,	15},
-	{25000,	36,	25,	15},
-	{25175,	26,	40,	33},
-	{25200,	30,	21,	15},
-	{26000,	36,	26,	15},
-	{27000,	30,	21,	14},
-	{27027,	18,	100,	111},
-	{27500,	30,	29,	19},
-	{28000,	34,	30,	17},
-	{28320,	26,	30,	22},
-	{28322,	32,	42,	25},
-	{28750,	24,	23,	18},
-	{29000,	30,	29,	18},
-	{29750,	32,	30,	17},
-	{30000,	30,	25,	15},
-	{30750,	30,	41,	24},
-	{31000,	30,	31,	18},
-	{31500,	30,	28,	16},
-	{32000,	30,	32,	18},
-	{32500,	28,	32,	19},
-	{33000,	24,	22,	15},
-	{34000,	28,	30,	17},
-	{35000,	26,	32,	19},
-	{35500,	24,	30,	19},
-	{36000,	26,	26,	15},
-	{36750,	26,	46,	26},
-	{37000,	24,	23,	14},
-	{37762,	22,	40,	26},
-	{37800,	20,	21,	15},
-	{38000,	24,	27,	16},
-	{38250,	24,	34,	20},
-	{39000,	24,	26,	15},
-	{40000,	24,	32,	18},
-	{40500,	20,	21,	14},
-	{40541,	22,	147,	89},
-	{40750,	18,	19,	14},
-	{41000,	16,	17,	14},
-	{41500,	22,	44,	26},
-	{41540,	22,	44,	26},
-	{42000,	18,	21,	15},
-	{42500,	22,	45,	26},
-	{43000,	20,	43,	27},
-	{43163,	20,	24,	15},
-	{44000,	18,	22,	15},
-	{44900,	20,	108,	65},
-	{45000,	20,	25,	15},
-	{45250,	20,	52,	31},
-	{46000,	18,	23,	15},
-	{46750,	20,	45,	26},
-	{47000,	20,	40,	23},
-	{48000,	18,	24,	15},
-	{49000,	18,	49,	30},
-	{49500,	16,	22,	15},
-	{50000,	18,	25,	15},
-	{50500,	18,	32,	19},
-	{51000,	18,	34,	20},
-	{52000,	18,	26,	15},
-	{52406,	14,	34,	25},
-	{53000,	16,	22,	14},
-	{54000,	16,	24,	15},
-	{54054,	16,	173,	108},
-	{54500,	14,	24,	17},
-	{55000,	12,	22,	18},
-	{56000,	14,	45,	31},
-	{56250,	16,	25,	15},
-	{56750,	14,	25,	17},
-	{57000,	16,	27,	16},
-	{58000,	16,	43,	25},
-	{58250,	16,	38,	22},
-	{58750,	16,	40,	23},
-	{59000,	14,	26,	17},
-	{59341,	14,	40,	26},
-	{59400,	16,	44,	25},
-	{60000,	16,	32,	18},
-	{60500,	12,	39,	29},
-	{61000,	14,	49,	31},
-	{62000,	14,	37,	23},
-	{62250,	14,	42,	26},
-	{63000,	12,	21,	15},
-	{63500,	14,	28,	17},
-	{64000,	12,	27,	19},
-	{65000,	14,	32,	19},
-	{65250,	12,	29,	20},
-	{65500,	12,	32,	22},
-	{66000,	12,	22,	15},
-	{66667,	14,	38,	22},
-	{66750,	10,	21,	17},
-	{67000,	14,	33,	19},
-	{67750,	14,	58,	33},
-	{68000,	14,	30,	17},
-	{68179,	14,	46,	26},
-	{68250,	14,	46,	26},
-	{69000,	12,	23,	15},
-	{70000,	12,	28,	18},
-	{71000,	12,	30,	19},
-	{72000,	12,	24,	15},
-	{73000,	10,	23,	17},
-	{74000,	12,	23,	14},
-	{74176,	8,	100,	91},
-	{74250,	10,	22,	16},
-	{74481,	12,	43,	26},
-	{74500,	10,	29,	21},
-	{75000,	12,	25,	15},
-	{75250,	10,	39,	28},
-	{76000,	12,	27,	16},
-	{77000,	12,	53,	31},
-	{78000,	12,	26,	15},
-	{78750,	12,	28,	16},
-	{79000,	10,	38,	26},
-	{79500,	10,	28,	19},
-	{80000,	12,	32,	18},
-	{81000,	10,	21,	14},
-	{81081,	6,	100,	111},
-	{81624,	8,	29,	24},
-	{82000,	8,	17,	14},
-	{83000,	10,	40,	26},
-	{83950,	10,	28,	18},
-	{84000,	10,	28,	18},
-	{84750,	6,	16,	17},
-	{85000,	6,	17,	18},
-	{85250,	10,	30,	19},
-	{85750,	10,	27,	17},
-	{86000,	10,	43,	27},
-	{87000,	10,	29,	18},
-	{88000,	10,	44,	27},
-	{88500,	10,	41,	25},
-	{89000,	10,	28,	17},
-	{89012,	6,	90,	91},
-	{89100,	10,	33,	20},
-	{90000,	10,	25,	15},
-	{91000,	10,	32,	19},
-	{92000,	10,	46,	27},
-	{93000,	10,	31,	18},
-	{94000,	10,	40,	23},
-	{94500,	10,	28,	16},
-	{95000,	10,	44,	25},
-	{95654,	10,	39,	22},
-	{95750,	10,	39,	22},
-	{96000,	10,	32,	18},
-	{97000,	8,	23,	16},
-	{97750,	8,	42,	29},
-	{98000,	8,	45,	31},
-	{99000,	8,	22,	15},
-	{99750,	8,	34,	23},
-	{100000,	6,	20,	18},
-	{100500,	6,	19,	17},
-	{101000,	6,	37,	33},
-	{101250,	8,	21,	14},
-	{102000,	6,	17,	15},
-	{102250,	6,	25,	22},
-	{103000,	8,	29,	19},
-	{104000,	8,	37,	24},
-	{105000,	8,	28,	18},
-	{106000,	8,	22,	14},
-	{107000,	8,	46,	29},
-	{107214,	8,	27,	17},
-	{108000,	8,	24,	15},
-	{108108,	8,	173,	108},
-	{109000,	6,	23,	19},
-	{110000,	6,	22,	18},
-	{110013,	6,	22,	18},
-	{110250,	8,	49,	30},
-	{110500,	8,	36,	22},
-	{111000,	8,	23,	14},
-	{111264,	8,	150,	91},
-	{111375,	8,	33,	20},
-	{112000,	8,	63,	38},
-	{112500,	8,	25,	15},
-	{113100,	8,	57,	34},
-	{113309,	8,	42,	25},
-	{114000,	8,	27,	16},
-	{115000,	6,	23,	18},
-	{116000,	8,	43,	25},
-	{117000,	8,	26,	15},
-	{117500,	8,	40,	23},
-	{118000,	6,	38,	29},
-	{119000,	8,	30,	17},
-	{119500,	8,	46,	26},
-	{119651,	8,	39,	22},
-	{120000,	8,	32,	18},
-	{121000,	6,	39,	29},
-	{121250,	6,	31,	23},
-	{121750,	6,	23,	17},
-	{122000,	6,	42,	31},
-	{122614,	6,	30,	22},
-	{123000,	6,	41,	30},
-	{123379,	6,	37,	27},
-	{124000,	6,	51,	37},
-	{125000,	6,	25,	18},
-	{125250,	4,	13,	14},
-	{125750,	4,	27,	29},
-	{126000,	6,	21,	15},
-	{127000,	6,	24,	17},
-	{127250,	6,	41,	29},
-	{128000,	6,	27,	19},
-	{129000,	6,	43,	30},
-	{129859,	4,	25,	26},
-	{130000,	6,	26,	18},
-	{130250,	6,	42,	29},
-	{131000,	6,	32,	22},
-	{131500,	6,	38,	26},
-	{131850,	6,	41,	28},
-	{132000,	6,	22,	15},
-	{132750,	6,	28,	19},
-	{133000,	6,	34,	23},
-	{133330,	6,	37,	25},
-	{134000,	6,	61,	41},
-	{135000,	6,	21,	14},
-	{135250,	6,	167,	111},
-	{136000,	6,	62,	41},
-	{137000,	6,	35,	23},
-	{138000,	6,	23,	15},
-	{138500,	6,	40,	26},
-	{138750,	6,	37,	24},
-	{139000,	6,	34,	22},
-	{139050,	6,	34,	22},
-	{139054,	6,	34,	22},
-	{140000,	6,	28,	18},
-	{141000,	6,	36,	23},
-	{141500,	6,	22,	14},
-	{142000,	6,	30,	19},
-	{143000,	6,	27,	17},
-	{143472,	4,	17,	16},
-	{144000,	6,	24,	15},
-	{145000,	6,	29,	18},
-	{146000,	6,	47,	29},
-	{146250,	6,	26,	16},
-	{147000,	6,	49,	30},
-	{147891,	6,	23,	14},
-	{148000,	6,	23,	14},
-	{148250,	6,	28,	17},
-	{148352,	4,	100,	91},
-	{148500,	6,	33,	20},
-	{149000,	6,	48,	29},
-	{150000,	6,	25,	15},
-	{151000,	4,	19,	17},
-	{152000,	6,	27,	16},
-	{152280,	6,	44,	26},
-	{153000,	6,	34,	20},
-	{154000,	6,	53,	31},
-	{155000,	6,	31,	18},
-	{155250,	6,	50,	29},
-	{155750,	6,	45,	26},
-	{156000,	6,	26,	15},
-	{157000,	6,	61,	35},
-	{157500,	6,	28,	16},
-	{158000,	6,	65,	37},
-	{158250,	6,	44,	25},
-	{159000,	6,	53,	30},
-	{159500,	6,	39,	22},
-	{160000,	6,	32,	18},
-	{161000,	4,	31,	26},
-	{162000,	4,	18,	15},
-	{162162,	4,	131,	109},
-	{162500,	4,	53,	44},
-	{163000,	4,	29,	24},
-	{164000,	4,	17,	14},
-	{165000,	4,	22,	18},
-	{166000,	4,	32,	26},
-	{167000,	4,	26,	21},
-	{168000,	4,	46,	37},
-	{169000,	4,	104,	83},
-	{169128,	4,	64,	51},
-	{169500,	4,	39,	31},
-	{170000,	4,	34,	27},
-	{171000,	4,	19,	15},
-	{172000,	4,	51,	40},
-	{172750,	4,	32,	25},
-	{172800,	4,	32,	25},
-	{173000,	4,	41,	32},
-	{174000,	4,	49,	38},
-	{174787,	4,	22,	17},
-	{175000,	4,	35,	27},
-	{176000,	4,	30,	23},
-	{177000,	4,	38,	29},
-	{178000,	4,	29,	22},
-	{178500,	4,	37,	28},
-	{179000,	4,	53,	40},
-	{179500,	4,	73,	55},
-	{180000,	4,	20,	15},
-	{181000,	4,	55,	41},
-	{182000,	4,	31,	23},
-	{183000,	4,	42,	31},
-	{184000,	4,	30,	22},
-	{184750,	4,	26,	19},
-	{185000,	4,	37,	27},
-	{186000,	4,	51,	37},
-	{187000,	4,	36,	26},
-	{188000,	4,	32,	23},
-	{189000,	4,	21,	15},
-	{190000,	4,	38,	27},
-	{190960,	4,	41,	29},
-	{191000,	4,	41,	29},
-	{192000,	4,	27,	19},
-	{192250,	4,	37,	26},
-	{193000,	4,	20,	14},
-	{193250,	4,	53,	37},
-	{194000,	4,	23,	16},
-	{194208,	4,	23,	16},
-	{195000,	4,	26,	18},
-	{196000,	4,	45,	31},
-	{197000,	4,	35,	24},
-	{197750,	4,	41,	28},
-	{198000,	4,	22,	15},
-	{198500,	4,	25,	17},
-	{199000,	4,	28,	19},
-	{200000,	4,	37,	25},
-	{201000,	4,	61,	41},
-	{202000,	4,	112,	75},
-	{202500,	4,	21,	14},
-	{203000,	4,	146,	97},
-	{204000,	4,	62,	41},
-	{204750,	4,	44,	29},
-	{205000,	4,	38,	25},
-	{206000,	4,	29,	19},
-	{207000,	4,	23,	15},
-	{207500,	4,	40,	26},
-	{208000,	4,	37,	24},
-	{208900,	4,	48,	31},
-	{209000,	4,	48,	31},
-	{209250,	4,	31,	20},
-	{210000,	4,	28,	18},
-	{211000,	4,	25,	16},
-	{212000,	4,	22,	14},
-	{213000,	4,	30,	19},
-	{213750,	4,	38,	24},
-	{214000,	4,	46,	29},
-	{214750,	4,	35,	22},
-	{215000,	4,	43,	27},
-	{216000,	4,	24,	15},
-	{217000,	4,	37,	23},
-	{218000,	4,	42,	26},
-	{218250,	4,	42,	26},
-	{218750,	4,	34,	21},
-	{219000,	4,	47,	29},
-	{220000,	4,	44,	27},
-	{220640,	4,	49,	30},
-	{220750,	4,	36,	22},
-	{221000,	4,	36,	22},
-	{222000,	4,	23,	14},
-	{222525,	4,	28,	17},
-	{222750,	4,	33,	20},
-	{227000,	4,	37,	22},
-	{230250,	4,	29,	17},
-	{233500,	4,	38,	22},
-	{235000,	4,	40,	23},
-	{238000,	4,	30,	17},
-	{241500,	2,	17,	19},
-	{245250,	2,	20,	22},
-	{247750,	2,	22,	24},
-	{253250,	2,	15,	16},
-	{256250,	2,	18,	19},
-	{262500,	2,	31,	32},
-	{267250,	2,	66,	67},
-	{268500,	2,	94,	95},
-	{270000,	2,	14,	14},
-	{272500,	2,	77,	76},
-	{273750,	2,	57,	56},
-	{280750,	2,	24,	23},
-	{281250,	2,	23,	22},
-	{286000,	2,	17,	16},
-	{291750,	2,	26,	24},
-	{296703,	2,	56,	51},
-	{297000,	2,	22,	20},
-	{298000,	2,	21,	19},
-};
-
 static void intel_ddi_mode_set(struct drm_encoder *encoder,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode)
@@ -675,7 +292,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
 	int pipe = intel_crtc->pipe;
 	int type = intel_encoder->type;
 
-	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
+	DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
 		      port_name(port), pipe_name(pipe));
 
 	intel_crtc->eld_vld = false;
@@ -686,22 +303,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
 
 		intel_dp->DP = intel_dig_port->port_reversal |
 			       DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
-		switch (intel_dp->lane_count) {
-		case 1:
-			intel_dp->DP |= DDI_PORT_WIDTH_X1;
-			break;
-		case 2:
-			intel_dp->DP |= DDI_PORT_WIDTH_X2;
-			break;
-		case 4:
-			intel_dp->DP |= DDI_PORT_WIDTH_X4;
-			break;
-		default:
-			intel_dp->DP |= DDI_PORT_WIDTH_X4;
-			WARN(1, "Unexpected DP lane count %d\n",
-			     intel_dp->lane_count);
-			break;
-		}
+		intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
 
 		if (intel_dp->has_audio) {
 			DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
@@ -748,8 +350,8 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
 	}
 
 	if (num_encoders != 1)
-		WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
-		     intel_crtc->pipe);
+		WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders,
+		     pipe_name(intel_crtc->pipe));
 
 	BUG_ON(ret == NULL);
 	return ret;
@@ -802,30 +404,227 @@ void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
 	intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
 }
 
-static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2)
+#define LC_FREQ 2700
+#define LC_FREQ_2K (LC_FREQ * 2000)
+
+#define P_MIN 2
+#define P_MAX 64
+#define P_INC 2
+
+/* Constraints for PLL good behavior */
+#define REF_MIN 48
+#define REF_MAX 400
+#define VCO_MIN 2400
+#define VCO_MAX 4800
+
+#define ABS_DIFF(a, b) ((a > b) ? (a - b) : (b - a))
+
+struct wrpll_rnp {
+	unsigned p, n2, r2;
+};
+
+static unsigned wrpll_get_budget_for_freq(int clock)
+{
+	unsigned budget;
+
+	switch (clock) {
+	case 25175000:
+	case 25200000:
+	case 27000000:
+	case 27027000:
+	case 37762500:
+	case 37800000:
+	case 40500000:
+	case 40541000:
+	case 54000000:
+	case 54054000:
+	case 59341000:
+	case 59400000:
+	case 72000000:
+	case 74176000:
+	case 74250000:
+	case 81000000:
+	case 81081000:
+	case 89012000:
+	case 89100000:
+	case 108000000:
+	case 108108000:
+	case 111264000:
+	case 111375000:
+	case 148352000:
+	case 148500000:
+	case 162000000:
+	case 162162000:
+	case 222525000:
+	case 222750000:
+	case 296703000:
+	case 297000000:
+		budget = 0;
+		break;
+	case 233500000:
+	case 245250000:
+	case 247750000:
+	case 253250000:
+	case 298000000:
+		budget = 1500;
+		break;
+	case 169128000:
+	case 169500000:
+	case 179500000:
+	case 202000000:
+		budget = 2000;
+		break;
+	case 256250000:
+	case 262500000:
+	case 270000000:
+	case 272500000:
+	case 273750000:
+	case 280750000:
+	case 281250000:
+	case 286000000:
+	case 291750000:
+		budget = 4000;
+		break;
+	case 267250000:
+	case 268500000:
+		budget = 5000;
+		break;
+	default:
+		budget = 1000;
+		break;
+	}
+
+	return budget;
+}
+
+static void wrpll_update_rnp(uint64_t freq2k, unsigned budget,
+			     unsigned r2, unsigned n2, unsigned p,
+			     struct wrpll_rnp *best)
 {
-	u32 i;
+	uint64_t a, b, c, d, diff, diff_best;
 
-	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
-		if (clock <= wrpll_tmds_clock_table[i].clock)
-			break;
+	/* No best (r,n,p) yet */
+	if (best->p == 0) {
+		best->p = p;
+		best->n2 = n2;
+		best->r2 = r2;
+		return;
+	}
+
+	/*
+	 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
+	 * freq2k.
+	 *
+	 * delta = 1e6 *
+	 *	   abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
+	 *	   freq2k;
+	 *
+	 * and we would like delta <= budget.
+	 *
+	 * If the discrepancy is above the PPM-based budget, always prefer to
+	 * improve upon the previous solution.  However, if you're within the
+	 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
+	 */
+	a = freq2k * budget * p * r2;
+	b = freq2k * budget * best->p * best->r2;
+	diff = ABS_DIFF((freq2k * p * r2), (LC_FREQ_2K * n2));
+	diff_best = ABS_DIFF((freq2k * best->p * best->r2),
+			     (LC_FREQ_2K * best->n2));
+	c = 1000000 * diff;
+	d = 1000000 * diff_best;
+
+	if (a < c && b < d) {
+		/* If both are above the budget, pick the closer */
+		if (best->p * best->r2 * diff < p * r2 * diff_best) {
+			best->p = p;
+			best->n2 = n2;
+			best->r2 = r2;
+		}
+	} else if (a >= c && b < d) {
+		/* If A is below the threshold but B is above it?  Update. */
+		best->p = p;
+		best->n2 = n2;
+		best->r2 = r2;
+	} else if (a >= c && b >= d) {
+		/* Both are below the limit, so pick the higher n2/(r2*r2) */
+		if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
+			best->p = p;
+			best->n2 = n2;
+			best->r2 = r2;
+		}
+	}
+	/* Otherwise a < c && b >= d, do nothing */
+}
+
+static void
+intel_ddi_calculate_wrpll(int clock /* in Hz */,
+			  unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
+{
+	uint64_t freq2k;
+	unsigned p, n2, r2;
+	struct wrpll_rnp best = { 0, 0, 0 };
+	unsigned budget;
 
-	if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
-		i--;
+	freq2k = clock / 100;
 
-	*p = wrpll_tmds_clock_table[i].p;
-	*n2 = wrpll_tmds_clock_table[i].n2;
-	*r2 = wrpll_tmds_clock_table[i].r2;
+	budget = wrpll_get_budget_for_freq(clock);
 
-	if (wrpll_tmds_clock_table[i].clock != clock)
-		DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n",
-			 wrpll_tmds_clock_table[i].clock, clock);
+	/* Special case handling for 540 pixel clock: bypass WR PLL entirely
+	 * and directly pass the LC PLL to it. */
+	if (freq2k == 5400000) {
+		*n2_out = 2;
+		*p_out = 1;
+		*r2_out = 2;
+		return;
+	}
+
+	/*
+	 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
+	 * the WR PLL.
+	 *
+	 * We want R so that REF_MIN <= Ref <= REF_MAX.
+	 * Injecting R2 = 2 * R gives:
+	 *   REF_MAX * r2 > LC_FREQ * 2 and
+	 *   REF_MIN * r2 < LC_FREQ * 2
+	 *
+	 * Which means the desired boundaries for r2 are:
+	 *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
+	 *
+	 */
+	for (r2 = LC_FREQ * 2 / REF_MAX + 1;
+	     r2 <= LC_FREQ * 2 / REF_MIN;
+	     r2++) {
+
+		/*
+		 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
+		 *
+		 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
+		 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
+		 *   VCO_MAX * r2 > n2 * LC_FREQ and
+		 *   VCO_MIN * r2 < n2 * LC_FREQ)
+		 *
+		 * Which means the desired boundaries for n2 are:
+		 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
+		 */
+		for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
+		     n2 <= VCO_MAX * r2 / LC_FREQ;
+		     n2++) {
 
-	DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
-		      clock, *p, *n2, *r2);
+			for (p = P_MIN; p <= P_MAX; p += P_INC)
+				wrpll_update_rnp(freq2k, budget,
+						 r2, n2, p, &best);
+		}
+	}
+
+	*n2_out = best.n2;
+	*p_out = best.p;
+	*r2_out = best.r2;
+
+	DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
+		      clock, *p_out, *n2_out, *r2_out);
 }
 
-bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
@@ -835,6 +634,7 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 	int type = intel_encoder->type;
 	enum pipe pipe = intel_crtc->pipe;
 	uint32_t reg, val;
+	int clock = intel_crtc->config.port_clock;
 
 	/* TODO: reuse PLLs when possible (compare values) */
 
@@ -863,7 +663,7 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 		return true;
 
 	} else if (type == INTEL_OUTPUT_HDMI) {
-		int p, n2, r2;
+		unsigned p, n2, r2;
 
 		if (plls->wrpll1_refcount == 0) {
 			DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
@@ -885,7 +685,7 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 		WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
 		     "WRPLL already enabled\n");
 
-		intel_ddi_calculate_wrpll(clock, &p, &n2, &r2);
+		intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
 
 		val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
 		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
@@ -995,7 +795,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 			/* Can only use the always-on power well for eDP when
 			 * not using the panel fitter, and when not using motion
 			  * blur mitigation (which we don't support). */
-			if (dev_priv->pch_pf_size)
+			if (intel_crtc->config.pch_pfit.size)
 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
 			else
 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
@@ -1022,7 +822,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 
 	} else if (type == INTEL_OUTPUT_ANALOG) {
 		temp |= TRANS_DDI_MODE_SELECT_FDI;
-		temp |= (intel_crtc->fdi_lanes - 1) << 1;
+		temp |= (intel_crtc->config.fdi_lanes - 1) << 1;
 
 	} else if (type == INTEL_OUTPUT_DISPLAYPORT ||
 		   type == INTEL_OUTPUT_EDP) {
@@ -1030,25 +830,10 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 
 		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
 
-		switch (intel_dp->lane_count) {
-		case 1:
-			temp |= TRANS_DDI_PORT_WIDTH_X1;
-			break;
-		case 2:
-			temp |= TRANS_DDI_PORT_WIDTH_X2;
-			break;
-		case 4:
-			temp |= TRANS_DDI_PORT_WIDTH_X4;
-			break;
-		default:
-			temp |= TRANS_DDI_PORT_WIDTH_X4;
-			WARN(1, "Unsupported lane count %d\n",
-			     intel_dp->lane_count);
-		}
-
+		temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
 	} else {
-		WARN(1, "Invalid encoder type %d for pipe %d\n",
-		     intel_encoder->type, pipe);
+		WARN(1, "Invalid encoder type %d for pipe %c\n",
+		     intel_encoder->type, pipe_name(pipe));
 	}
 
 	I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
@@ -1148,7 +933,7 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 		}
 	}
 
-	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
+	DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
 
 	return false;
 }
@@ -1334,7 +1119,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 		ironlake_edp_backlight_on(intel_dp);
 	}
 
-	if (intel_crtc->eld_vld) {
+	if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
 		tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
 		tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
 		I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
@@ -1352,9 +1137,12 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
-	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
-	tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
-	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+	if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
+		tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+		tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) <<
+			 (pipe * 4));
+		I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+	}
 
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -1366,14 +1154,14 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
 {
 	if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
-		return 450;
+		return 450000;
 	else if ((I915_READ(LCPLL_CTL) & LCPLL_CLK_FREQ_MASK) ==
 		 LCPLL_CLK_FREQ_450)
-		return 450;
+		return 450000;
 	else if (IS_ULT(dev_priv->dev))
-		return 338;
+		return 337500;
 	else
-		return 540;
+		return 540000;
 }
 
 void intel_ddi_pll_init(struct drm_device *dev)
@@ -1386,7 +1174,7 @@ void intel_ddi_pll_init(struct drm_device *dev)
 	 * Don't even try to turn it on.
 	 */
 
-	DRM_DEBUG_KMS("CDCLK running at %dMHz\n",
+	DRM_DEBUG_KMS("CDCLK running at %dKHz\n",
 		      intel_ddi_get_cdclk_freq(dev_priv));
 
 	if (val & LCPLL_CD_SOURCE_FCLK)
@@ -1472,6 +1260,27 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
 		intel_dp_check_link_status(intel_dp);
 }
 
+static void intel_ddi_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+	u32 temp, flags = 0;
+
+	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+	if (temp & TRANS_DDI_PHSYNC)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (temp & TRANS_DDI_PVSYNC)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_ddi_destroy(struct drm_encoder *encoder)
 {
 	/* HDMI has nothing special to destroy, so we can go with this. */
@@ -1482,9 +1291,13 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder,
 				     struct intel_crtc_config *pipe_config)
 {
 	int type = encoder->type;
+	int port = intel_ddi_get_encoder_port(encoder);
 
 	WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
 
+	if (port == PORT_A)
+		pipe_config->cpu_transcoder = TRANSCODER_EDP;
+
 	if (type == INTEL_OUTPUT_HDMI)
 		return intel_hdmi_compute_config(encoder, pipe_config);
 	else
@@ -1518,16 +1331,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 		return;
 	}
 
-	if (port != PORT_A) {
-		hdmi_connector = kzalloc(sizeof(struct intel_connector),
-					 GFP_KERNEL);
-		if (!hdmi_connector) {
-			kfree(dp_connector);
-			kfree(intel_dig_port);
-			return;
-		}
-	}
-
 	intel_encoder = &intel_dig_port->base;
 	encoder = &intel_encoder->base;
 
@@ -1541,12 +1344,11 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	intel_encoder->disable = intel_disable_ddi;
 	intel_encoder->post_disable = intel_ddi_post_disable;
 	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+	intel_encoder->get_config = intel_ddi_get_config;
 
 	intel_dig_port->port = port;
 	intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
 					DDI_BUF_PORT_REVERSAL;
-	if (hdmi_connector)
-		intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
 	intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
 
 	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
@@ -1554,7 +1356,21 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	intel_encoder->cloneable = false;
 	intel_encoder->hot_plug = intel_ddi_hot_plug;
 
-	if (hdmi_connector)
+	if (!intel_dp_init_connector(intel_dig_port, dp_connector)) {
+		drm_encoder_cleanup(encoder);
+		kfree(intel_dig_port);
+		kfree(dp_connector);
+		return;
+	}
+
+	if (intel_encoder->type != INTEL_OUTPUT_EDP) {
+		hdmi_connector = kzalloc(sizeof(struct intel_connector),
+					 GFP_KERNEL);
+		if (!hdmi_connector) {
+			return;
+		}
+
+		intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
 		intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
-	intel_dp_init_connector(intel_dig_port, dp_connector);
+	}
 }

File diff suppressed because it is too large
+ 183 - 403
drivers/gpu/drm/i915/intel_display.c


File diff suppressed because it is too large
+ 445 - 214
drivers/gpu/drm/i915/intel_dp.c


+ 141 - 45
drivers/gpu/drm/i915/intel_drv.h

@@ -120,7 +120,6 @@ struct intel_encoder {
 	struct intel_crtc *new_crtc;
 
 	int type;
-	bool needs_tv_clock;
 	/*
 	 * Intel hw has only one MUX where encoders could be clone, hence a
 	 * simple flag is enough to compute the possible_clones mask.
@@ -140,6 +139,12 @@ struct intel_encoder {
 	 * the encoder is active. If the encoder is enabled it also set the pipe
 	 * it is connected to in the pipe parameter. */
 	bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
+	/* Reconstructs the equivalent mode flags for the current hardware
+	 * state. This must be called _after_ display->get_pipe_config has
+	 * pre-filled the pipe config. Note that intel_encoder->base.crtc must
+	 * be set correctly before calling this function. */
+	void (*get_config)(struct intel_encoder *,
+			   struct intel_crtc_config *pipe_config);
 	int crtc_mask;
 	enum hpd_pin hpd_pin;
 };
@@ -177,7 +182,30 @@ struct intel_connector {
 	u8 polled;
 };
 
+typedef struct dpll {
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int	dot;
+	int	vco;
+	int	m;
+	int	p;
+} intel_clock_t;
+
 struct intel_crtc_config {
+	/**
+	 * quirks - bitfield with hw state readout quirks
+	 *
+	 * For various reasons the hw state readout code might not be able to
+	 * completely faithfully read out the current state. These cases are
+	 * tracked with quirk flags so that fastboot and state checker can act
+	 * accordingly.
+	 */
+#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
+	unsigned long quirks;
+
 	struct drm_display_mode requested_mode;
 	struct drm_display_mode adjusted_mode;
 	/* This flag must be set by the encoder's compute_config callback if it
@@ -201,29 +229,67 @@ struct intel_crtc_config {
 	/* DP has a bunch of special case unfortunately, so mark the pipe
 	 * accordingly. */
 	bool has_dp_encoder;
+
+	/*
+	 * Enable dithering, used when the selected pipe bpp doesn't match the
+	 * plane bpp.
+	 */
 	bool dither;
 
 	/* Controls for the clock computation, to override various stages. */
 	bool clock_set;
 
+	/* SDVO TV has a bunch of special case. To make multifunction encoders
+	 * work correctly, we need to track this at runtime.*/
+	bool sdvo_tv_clock;
+
+	/*
+	 * crtc bandwidth limit, don't increase pipe bpp or clock if not really
+	 * required. This is set in the 2nd loop of calling encoder's
+	 * ->compute_config if the first pick doesn't work out.
+	 */
+	bool bw_constrained;
+
 	/* Settings for the intel dpll used on pretty much everything but
 	 * haswell. */
-	struct dpll {
-		unsigned n;
-		unsigned m1, m2;
-		unsigned p1, p2;
-	} dpll;
+	struct dpll dpll;
+
+	/* Selected dpll when shared or DPLL_ID_PRIVATE. */
+	enum intel_dpll_id shared_dpll;
+
+	/* Actual register state of the dpll, for shared dpll cross-checking. */
+	struct intel_dpll_hw_state dpll_hw_state;
 
 	int pipe_bpp;
 	struct intel_link_m_n dp_m_n;
-	/**
-	 * This is currently used by DP and HDMI encoders since those can have a
-	 * target pixel clock != the port link clock (which is currently stored
-	 * in adjusted_mode->clock).
+
+	/*
+	 * Frequence the dpll for the port should run at. Differs from the
+	 * adjusted dotclock e.g. for DP or 12bpc hdmi mode.
 	 */
-	int pixel_target_clock;
+	int port_clock;
+
 	/* Used by SDVO (and if we ever fix it, HDMI). */
 	unsigned pixel_multiplier;
+
+	/* Panel fitter controls for gen2-gen4 + VLV */
+	struct {
+		u32 control;
+		u32 pgm_ratios;
+		u32 lvds_border_bits;
+	} gmch_pfit;
+
+	/* Panel fitter placement and size for Ironlake+ */
+	struct {
+		u32 pos;
+		u32 size;
+	} pch_pfit;
+
+	/* FDI configuration, only valid if has_pch_encoder is set. */
+	int fdi_lanes;
+	struct intel_link_m_n fdi_m_n;
+
+	bool ips_enabled;
 };
 
 struct intel_crtc {
@@ -242,7 +308,6 @@ struct intel_crtc {
 	bool lowfreq_avail;
 	struct intel_overlay *overlay;
 	struct intel_unpin_work *unpin_work;
-	int fdi_lanes;
 
 	atomic_t unpin_work_count;
 
@@ -259,12 +324,14 @@ struct intel_crtc {
 
 	struct intel_crtc_config config;
 
-	/* We can share PLLs across outputs if the timings match */
-	struct intel_pch_pll *pch_pll;
 	uint32_t ddi_pll_sel;
 
 	/* reset counter value when the last flip was submitted */
 	unsigned int reset_counter;
+
+	/* Access to these should be protected by dev_priv->irq_lock. */
+	bool cpu_fifo_underrun_disabled;
+	bool pch_fifo_underrun_disabled;
 };
 
 struct intel_plane {
@@ -279,6 +346,18 @@ struct intel_plane {
 	unsigned int crtc_w, crtc_h;
 	uint32_t src_x, src_y;
 	uint32_t src_w, src_h;
+
+	/* Since we need to change the watermarks before/after
+	 * enabling/disabling the planes, we need to store the parameters here
+	 * as the other pieces of the struct may not reflect the values we want
+	 * for the watermark calculations. Currently only Haswell uses this.
+	 */
+	struct {
+		bool enable;
+		uint8_t bytes_per_pixel;
+		uint32_t horiz_pixels;
+	} wm;
+
 	void (*update_plane)(struct drm_plane *plane,
 			     struct drm_framebuffer *fb,
 			     struct drm_i915_gem_object *obj,
@@ -411,7 +490,6 @@ struct intel_dp {
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
-	bool is_pch_edp;
 	uint8_t train_set[4];
 	int panel_power_up_delay;
 	int panel_power_down_delay;
@@ -431,6 +509,19 @@ struct intel_digital_port {
 	struct intel_hdmi hdmi;
 };
 
+static inline int
+vlv_dport_to_channel(struct intel_digital_port *dport)
+{
+	switch (dport->port) {
+	case PORT_B:
+		return 0;
+	case PORT_C:
+		return 1;
+	default:
+		BUG();
+	}
+}
+
 static inline struct drm_crtc *
 intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
 {
@@ -474,6 +565,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
+extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev,
 			    int hdmi_reg, enum port port);
@@ -488,13 +580,14 @@ extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_mark_busy(struct drm_device *dev);
-extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
+extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
+			       struct intel_ring_buffer *ring);
 extern void intel_mark_idle(struct drm_device *dev);
-extern bool intel_lvds_init(struct drm_device *dev);
+extern void intel_lvds_init(struct drm_device *dev);
 extern bool intel_is_dual_link_lvds(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int output_reg,
 			  enum port port);
-extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 				    struct intel_connector *intel_connector);
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
@@ -512,7 +605,6 @@ extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
@@ -524,12 +616,14 @@ extern void intel_panel_fini(struct intel_panel *panel);
 
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 				   struct drm_display_mode *adjusted_mode);
-extern void intel_pch_panel_fitting(struct drm_device *dev,
-				    int fitting_mode,
-				    const struct drm_display_mode *mode,
-				    struct drm_display_mode *adjusted_mode);
-extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
-extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
+extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
+				    struct intel_crtc_config *pipe_config,
+				    int fitting_mode);
+extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
+				     struct intel_crtc_config *pipe_config,
+				     int fitting_mode);
+extern void intel_panel_set_backlight(struct drm_device *dev,
+				      u32 level, u32 max);
 extern int intel_panel_setup_backlight(struct drm_connector *connector);
 extern void intel_panel_enable_backlight(struct drm_device *dev,
 					 enum pipe pipe);
@@ -553,11 +647,11 @@ extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
 extern void intel_encoder_destroy(struct drm_encoder *encoder);
 extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode);
-extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder);
 extern void intel_connector_dpms(struct drm_connector *, int mode);
 extern bool intel_connector_get_hw_state(struct intel_connector *connector);
 extern void intel_modeset_check_state(struct drm_device *dev);
 extern void intel_plane_restore(struct drm_plane *plane);
+extern void intel_plane_disable(struct drm_plane *plane);
 
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
@@ -565,19 +659,17 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
 	return to_intel_connector(connector)->encoder;
 }
 
-static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
-{
-	struct intel_digital_port *intel_dig_port =
-		container_of(encoder, struct intel_digital_port, base.base);
-	return &intel_dig_port->dp;
-}
-
 static inline struct intel_digital_port *
 enc_to_dig_port(struct drm_encoder *encoder)
 {
 	return container_of(encoder, struct intel_digital_port, base.base);
 }
 
+static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+{
+	return &enc_to_dig_port(encoder)->dp;
+}
+
 static inline struct intel_digital_port *
 dp_to_dig_port(struct intel_dp *intel_dp)
 {
@@ -607,6 +699,7 @@ intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
+extern void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
 
 struct intel_load_detect_pipe {
 	struct drm_framebuffer *release_fb;
@@ -660,13 +753,9 @@ extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
 
 extern void intel_init_clock_gating(struct drm_device *dev);
+extern void intel_suspend_hw(struct drm_device *dev);
 extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
-extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
-extern void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
-					 struct intel_link_m_n *m_n);
-extern void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
-					 struct intel_link_m_n *m_n);
 extern void intel_prepare_ddi(struct drm_device *dev);
 extern void hsw_fdi_link_train(struct drm_crtc *crtc);
 extern void intel_ddi_init(struct drm_device *dev, enum port port);
@@ -675,9 +764,7 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port);
 extern void intel_update_watermarks(struct drm_device *dev);
 extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
 					   uint32_t sprite_width,
-					   int pixel_size);
-extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe,
-			 struct drm_display_mode *mode);
+					   int pixel_size, bool enable);
 
 extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
 						    unsigned int tiling_mode,
@@ -689,8 +776,6 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 				     struct drm_file *file_priv);
 
-extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
-
 /* Power-related functions, located in intel_pm.c */
 extern void intel_init_pm(struct drm_device *dev);
 /* FBC */
@@ -701,7 +786,12 @@ extern void intel_update_fbc(struct drm_device *dev);
 extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 extern void intel_gpu_ips_teardown(void);
 
-extern bool intel_using_power_well(struct drm_device *dev);
+/* Power well */
+extern int i915_init_power_well(struct drm_device *dev);
+extern void i915_remove_power_well(struct drm_device *dev);
+
+extern bool intel_display_power_enabled(struct drm_device *dev,
+					enum intel_display_power_domain domain);
 extern void intel_init_power_well(struct drm_device *dev);
 extern void intel_set_power_well(struct drm_device *dev, bool enable);
 extern void intel_enable_gt_powersave(struct drm_device *dev);
@@ -719,7 +809,7 @@ extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
-extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
+extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
 extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
@@ -728,5 +818,11 @@ intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
 extern void intel_display_handle_reset(struct drm_device *dev);
+extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
+						  enum pipe pipe,
+						  bool enable);
+extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
+						 enum transcoder pch_transcoder,
+						 bool enable);
 
 #endif /* __INTEL_DRV_H__ */

+ 31 - 0
drivers/gpu/drm/i915/intel_dvo.c

@@ -53,6 +53,13 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
 		.slave_addr = CH7xxx_ADDR,
 		.dev_ops = &ch7xxx_ops,
 	},
+	{
+		.type = INTEL_DVO_CHIP_TMDS,
+		.name = "ch7xxx",
+		.dvo_reg = DVOC,
+		.slave_addr = 0x75, /* For some ch7010 */
+		.dev_ops = &ch7xxx_ops,
+	},
 	{
 		.type = INTEL_DVO_CHIP_LVDS,
 		.name = "ivch",
@@ -129,6 +136,26 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_dvo_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(intel_dvo->dev.dvo_reg);
+	if (tmp & DVO_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (tmp & DVO_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_disable_dvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -153,6 +180,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
 	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 }
 
+/* Special dpms function to support cloning between dvo/sdvo/crt. */
 static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 {
 	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
@@ -174,6 +202,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 		return;
 	}
 
+	/* We call connector dpms manually below in case pipe dpms doesn't
+	 * change due to cloning. */
 	if (mode == DRM_MODE_DPMS_ON) {
 		intel_dvo->base.connectors_active = true;
 
@@ -440,6 +470,7 @@ void intel_dvo_init(struct drm_device *dev)
 	intel_encoder->disable = intel_disable_dvo;
 	intel_encoder->enable = intel_enable_dvo;
 	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
+	intel_encoder->get_config = intel_dvo_get_config;
 	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
 
 	/* Now, try to find a controller */

+ 11 - 17
drivers/gpu/drm/i915/intel_fb.c

@@ -60,8 +60,9 @@ static struct fb_ops intelfb_ops = {
 static int intelfb_create(struct drm_fb_helper *helper,
 			  struct drm_fb_helper_surface_size *sizes)
 {
-	struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
-	struct drm_device *dev = ifbdev->helper.dev;
+	struct intel_fbdev *ifbdev =
+		container_of(helper, struct intel_fbdev, helper);
+	struct drm_device *dev = helper->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
@@ -108,7 +109,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 		goto out_unpin;
 	}
 
-	info->par = ifbdev;
+	info->par = helper;
 
 	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
 	if (ret)
@@ -217,7 +218,7 @@ static void intel_fbdev_destroy(struct drm_device *dev,
 int intel_fbdev_init(struct drm_device *dev)
 {
 	struct intel_fbdev *ifbdev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
 	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
@@ -242,7 +243,7 @@ int intel_fbdev_init(struct drm_device *dev)
 
 void intel_fbdev_initial_config(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* Due to peculiar init order wrt to hpd handling this is separate. */
 	drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32);
@@ -250,7 +251,7 @@ void intel_fbdev_initial_config(struct drm_device *dev)
 
 void intel_fbdev_fini(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	if (!dev_priv->fbdev)
 		return;
 
@@ -261,7 +262,7 @@ void intel_fbdev_fini(struct drm_device *dev)
 
 void intel_fbdev_set_suspend(struct drm_device *dev, int state)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_fbdev *ifbdev = dev_priv->fbdev;
 	struct fb_info *info;
 
@@ -274,7 +275,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
 	 * been restored from swap. If the object is stolen however, it will be
 	 * full of whatever garbage was left in there.
 	 */
-	if (!state && ifbdev->ifb.obj->stolen)
+	if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen)
 		memset_io(info->screen_base, 0, info->screen_size);
 
 	fb_set_suspend(info, state);
@@ -284,16 +285,14 @@ MODULE_LICENSE("GPL and additional rights");
 
 void intel_fb_output_poll_changed(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
 
 void intel_fb_restore_mode(struct drm_device *dev)
 {
 	int ret;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_mode_config *config = &dev->mode_config;
-	struct drm_plane *plane;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (INTEL_INFO(dev)->num_pipes == 0)
 		return;
@@ -304,10 +303,5 @@ void intel_fb_restore_mode(struct drm_device *dev)
 	if (ret)
 		DRM_DEBUG("failed to restore crtc mode\n");
 
-	/* Be sure to shut off any planes that may be active */
-	list_for_each_entry(plane, &config->plane_list, head)
-		if (plane->enabled)
-			plane->funcs->disable_plane(plane);
-
 	drm_modeset_unlock_all(dev);
 }

+ 151 - 7
drivers/gpu/drm/i915/intel_hdmi.c

@@ -602,7 +602,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	u32 hdmi_val;
 
 	hdmi_val = SDVO_ENCODING_HDMI;
-	if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
+	if (!HAS_PCH_SPLIT(dev))
 		hdmi_val |= intel_hdmi->color_range;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
@@ -658,6 +658,28 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_hdmi_get_config(struct intel_encoder *encoder,
+				  struct intel_crtc_config *pipe_config)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(intel_hdmi->hdmi_reg);
+
+	if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_enable_hdmi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
@@ -697,6 +719,14 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
 		I915_WRITE(intel_hdmi->hdmi_reg, temp);
 		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
+
+	if (IS_VALLEYVIEW(dev)) {
+		struct intel_digital_port *dport =
+			enc_to_dig_port(&encoder->base);
+		int channel = vlv_dport_to_channel(dport);
+
+		vlv_wait_port_ready(dev_priv, channel);
+	}
 }
 
 static void intel_disable_hdmi(struct intel_encoder *encoder)
@@ -775,6 +805,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
+	int desired_bpp;
 
 	if (intel_hdmi->color_range_auto) {
 		/* See CEA-861-E - 5.1 Default Encoding Parameters */
@@ -794,14 +826,29 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	/*
 	 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
 	 * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
-	 * outputs.
+	 * outputs. We also need to check that the higher clock still fits
+	 * within limits.
 	 */
-	if (pipe_config->pipe_bpp > 8*3 && HAS_PCH_SPLIT(dev)) {
-		DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
-		pipe_config->pipe_bpp = 12*3;
+	if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000
+	    && HAS_PCH_SPLIT(dev)) {
+		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
+		desired_bpp = 12*3;
+
+		/* Need to adjust the port link by 1.5x for 12bpc. */
+		pipe_config->port_clock = clock_12bpc;
 	} else {
-		DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
-		pipe_config->pipe_bpp = 8*3;
+		DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n");
+		desired_bpp = 8*3;
+	}
+
+	if (!pipe_config->bw_constrained) {
+		DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI\n", desired_bpp);
+		pipe_config->pipe_bpp = desired_bpp;
+	}
+
+	if (adjusted_mode->clock > 225000) {
+		DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
+		return false;
 	}
 
 	return true;
@@ -955,6 +1002,97 @@ done:
 	return 0;
 }
 
+static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(encoder->base.crtc);
+	int port = vlv_dport_to_channel(dport);
+	int pipe = intel_crtc->pipe;
+	u32 val;
+
+	if (!IS_VALLEYVIEW(dev))
+		return;
+
+	/* Enable clock channels for this port */
+	val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
+	val = 0;
+	if (pipe)
+		val |= (1<<21);
+	else
+		val &= ~(1<<21);
+	val |= 0x001000c4;
+	vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
+
+	/* HDMI 1.0V-2dB */
+	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0);
+	vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port),
+			 0x2b245f5f);
+	vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
+			 0x5578b83a);
+	vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port),
+			 0x0c782040);
+	vlv_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port),
+			 0x2b247878);
+	vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
+			 0x00002000);
+	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
+			 DPIO_TX_OCALINIT_EN);
+
+	/* Program lane clock */
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
+			 0x00760018);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
+			 0x00400888);
+}
+
+static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int port = vlv_dport_to_channel(dport);
+
+	if (!IS_VALLEYVIEW(dev))
+		return;
+
+	/* Program Tx lane resets to default */
+	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
+			 DPIO_PCS_TX_LANE2_RESET |
+			 DPIO_PCS_TX_LANE1_RESET);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port),
+			 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
+			 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
+			 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
+			 DPIO_PCS_CLK_SOFT_RESET);
+
+	/* Fix up inter-pair skew failure */
+	vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
+	vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
+	vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
+
+	vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
+			 0x00002000);
+	vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
+			 DPIO_TX_OCALINIT_EN);
+}
+
+static void intel_hdmi_post_disable(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	int port = vlv_dport_to_channel(dport);
+
+	/* Reset lanes to avoid HDMI flicker (VLV w/a) */
+	mutex_lock(&dev_priv->dpio_lock);
+	vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000);
+	vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060);
+	mutex_unlock(&dev_priv->dpio_lock);
+}
+
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
 	drm_sysfs_connector_remove(connector);
@@ -1094,6 +1232,12 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 	intel_encoder->enable = intel_enable_hdmi;
 	intel_encoder->disable = intel_disable_hdmi;
 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
+	intel_encoder->get_config = intel_hdmi_get_config;
+	if (IS_VALLEYVIEW(dev)) {
+		intel_encoder->pre_enable = intel_hdmi_pre_enable;
+		intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
+		intel_encoder->post_disable = intel_hdmi_post_disable;
+	}
 
 	intel_encoder->type = INTEL_OUTPUT_HDMI;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);

Some files were not shown because too many files changed in this diff