<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.comp.video.dri.devel">
    <title>gmane.comp.video.dri.devel</title>
    <link>http://blog.gmane.org/gmane.comp.video.dri.devel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69618"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69617"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69612"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69611"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69610"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69606"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69603"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69602"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69598"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69597"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69594"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69593"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69592"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69591"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69590"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69589"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69588"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69587"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69586"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.video.dri.devel/69585"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69618">
    <title>[PATCH] drm/radeon: fix typo in trinity tiling setup</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69618</link>
    <description>&lt;pre&gt;From: Alex Deucher &amp;lt;alexander.deucher&amp;lt; at &amp;gt;amd.com&amp;gt;

Using the wrong union.

Signed-off-by: Alex Deucher &amp;lt;alexander.deucher&amp;lt; at &amp;gt;amd.com&amp;gt;
Cc: stable&amp;lt; at &amp;gt;vger.kernel.org
---
 drivers/gpu/drm/radeon/ni.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index b01c2dd..ce4e7cc 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -865,7 +865,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void cayman_gpu_init(struct radeon_device *rdev)
 
 /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
 if (rdev-&amp;gt;flags &amp;amp; RADEON_IS_IGP)
-rdev-&amp;gt;config.evergreen.tile_config |= 1 &amp;lt;&amp;lt; 4;
+rdev-&amp;gt;config.cayman.tile_config |= 1 &amp;lt;&amp;lt; 4;
 else
 rdev-&amp;gt;config.cayman.tile_config |=
 ((mc_arb_ramcfg &amp;amp; NOOFBANK_MASK) &amp;gt;&amp;gt; NOOFBANK_SHIFT) &amp;lt;&amp;lt; 4;
&lt;/pre&gt;</description>
    <dc:creator>alexdeucher&lt; at &gt;gmail.com</dc:creator>
    <dc:date>2012-05-25T02:55:15</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69617">
    <title>drm/i915 3.5 merge window: gen6_sanitize_pm errors</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69617</link>
    <description>&lt;pre&gt;These guys seem to be recently introduced:

  [drm:gen6_sanitize_pm] *ERROR* Power management discrepancy:
GEN6_RP_INTERRUPT_LIMITS expected 17000000, was 12060000
  [drm:gen6_sanitize_pm] *ERROR* Power management discrepancy:
GEN6_RP_INTERRUPT_LIMITS expected 17070000, was 17000000

This is on my SNB Macbook Air.

Everything seems to *work*, which makes me think:

 - that error isn't really so big a deal that you have to *SHOUT* about it.

 - I wonder how valid the discrepancy checking code is to begin with.

Hmm?

              Linus
&lt;/pre&gt;</description>
    <dc:creator>Linus Torvalds</dc:creator>
    <dc:date>2012-05-25T02:27:04</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69612">
    <title>[Bug 50325] Glyphy bad render on r600g (software render is fine)</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69612</link>
    <description>&lt;pre&gt;https://bugs.freedesktop.org/show_bug.cgi?id=50325

--- Comment #2 from Török Edwin &amp;lt;edwin+mesa&amp;lt; at &amp;gt;etorok.net&amp;gt; 2012-05-24 14:57:24 PDT ---
Created attachment 62080
  --&amp;gt; https://bugs.freedesktop.org/attachment.cgi?id=62080
sw-good.png

&lt;/pre&gt;</description>
    <dc:creator>bugzilla-daemon&lt; at &gt;freedesktop.org</dc:creator>
    <dc:date>2012-05-24T21:57:24</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69611">
    <title>[Bug 50325] Glyphy bad render on r600g (software render is fine)</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69611</link>
    <description>&lt;pre&gt;https://bugs.freedesktop.org/show_bug.cgi?id=50325

--- Comment #1 from Török Edwin &amp;lt;edwin+mesa&amp;lt; at &amp;gt;etorok.net&amp;gt; 2012-05-24 14:57:08 PDT ---
Created attachment 62079
  --&amp;gt; https://bugs.freedesktop.org/attachment.cgi?id=62079
r600g-bad.png

&lt;/pre&gt;</description>
    <dc:creator>bugzilla-daemon&lt; at &gt;freedesktop.org</dc:creator>
    <dc:date>2012-05-24T21:57:08</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69610">
    <title>[Bug 50325] New: Glyphy bad render on r600g (software render is fine)</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69610</link>
    <description>&lt;pre&gt;https://bugs.freedesktop.org/show_bug.cgi?id=50325

             Bug #: 50325
           Summary: Glyphy bad render on r600g (software render is fine)
    Classification: Unclassified
           Product: Mesa
           Version: 8.0
          Platform: x86-64 (AMD64)
        OS/Version: Linux (All)
            Status: NEW
          Severity: normal
          Priority: medium
         Component: Drivers/Gallium/r600
        AssignedTo: dri-devel&amp;lt; at &amp;gt;lists.freedesktop.org
        ReportedBy: edwin+mesa&amp;lt; at &amp;gt;etorok.net


Created attachment 62078
  --&amp;gt; https://bugs.freedesktop.org/attachment.cgi?id=62078
apitrace (cf. https://github.com/apitrace/apitrace/tree/1.0)

I just tried Glyphy on r600g and the output is very bad.
Don't know if its Glyphy bug or Mesa bug, but if I force software rendering in
Mesa then I do see the output.

Attached screenshots of bad (r600g) and good (software render).

The bad render was obtained by:
demo/glyphy-demo

The good one:
LIBGL_ALWAYS_SOFTWARE=1 demo/glyphy-demo

I tested on:
OpenGL vendor string: X.Org
OpenGL renderer string: Gallium 0.4 on AMD RV730
OpenGL version string: 2.1 Mesa 8.0.2
OpenGL shading language version string: 1.20

I'll try to test on mesa git later to see if its still an issue there.

Also attached is a an apitrace, and the bad render can be reproduced with:
build/glretrace lt-glyphy-demo.trace

The good render (initialization a bit slow, but works):
LIBGL_ALWAYS_SOFTWARE=1 build/glretrace lt-glyphy-demo.trace

The source code for Glyphy can be found here:
https://code.google.com/p/glyphy/source/checkout

&lt;/pre&gt;</description>
    <dc:creator>bugzilla-daemon&lt; at &gt;freedesktop.org</dc:creator>
    <dc:date>2012-05-24T21:56:46</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69606">
    <title>[PATCH 12/14] drm/i915: cache hdmi edid</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69606</link>
    <description>&lt;pre&gt;Like the previous patches.

While at it also kill a stale comment - we've moved hdmi audio
detection from -&amp;gt;get_modes to -&amp;gt;detect and the audio property handling
functions.

Signed-Off-by: Daniel Vetter &amp;lt;daniel.vetter&amp;lt; at &amp;gt;ffwll.ch&amp;gt;
---
 drivers/gpu/drm/i915/intel_drv.h  |    1 +
 drivers/gpu/drm/i915/intel_hdmi.c |   48 +++++++++++++++++++++++--------------
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3b6f716..8693551 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -301,6 +301,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct intel_hdmi {
 enum hdmi_force_audio force_audio;
 void (*write_infoframe)(struct drm_encoder *encoder,
 struct dip_infoframe *frame);
+struct edid *cached_edid;
 };
 
 static inline struct drm_crtc *
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 2ead3bf..373d252 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -452,19 +452,37 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
 return true;
 }
 
+struct edid *
+intel_hdmi_get_edid(struct drm_connector *connector)
+{
+struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+struct drm_i915_private *dev_priv = connector-&amp;gt;dev-&amp;gt;dev_private;
+
+if (!intel_hdmi-&amp;gt;cached_edid) {
+struct i2c_adapter *adapter;
+
+adapter = intel_gmbus_get_adapter(dev_priv,
+  intel_hdmi-&amp;gt;ddc_bus);
+intel_hdmi-&amp;gt;cached_edid = drm_get_edid(connector, adapter);
+}
+
+return intel_hdmi-&amp;gt;cached_edid;
+}
+
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-struct drm_i915_private *dev_priv = connector-&amp;gt;dev-&amp;gt;dev_private;
 struct edid *edid;
 enum drm_connector_status status = connector_status_disconnected;
 
+/* Clean the edid cache. */
+kfree(intel_hdmi-&amp;gt;cached_edid);
+intel_hdmi-&amp;gt;cached_edid = NULL;
+
 intel_hdmi-&amp;gt;has_hdmi_sink = false;
 intel_hdmi-&amp;gt;has_audio = false;
-edid = drm_get_edid(connector,
-    intel_gmbus_get_adapter(dev_priv,
-    intel_hdmi-&amp;gt;ddc_bus));
+edid = intel_hdmi_get_edid(connector);
 
 if (edid) {
 if (edid-&amp;gt;input &amp;amp; DRM_EDID_INPUT_DIGITAL) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -477,6 +495,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; intel_hdmi_detect(struct drm_connector *connector, bool force)
 connector-&amp;gt;display_info.raw_edid = NULL;
 kfree(edid);
 }
+intel_hdmi-&amp;gt;cached_edid = edid;
 
 if (status == connector_status_connected) {
 if (intel_hdmi-&amp;gt;force_audio != HDMI_AUDIO_AUTO)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -489,29 +508,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; intel_hdmi_detect(struct drm_connector *connector, bool force)
 
 static int intel_hdmi_get_modes(struct drm_connector *connector)
 {
-struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-struct drm_i915_private *dev_priv = connector-&amp;gt;dev-&amp;gt;dev_private;
-
-/* We should parse the EDID data and find out if it's an HDMI sink so
- * we can send audio to it.
- */
+struct edid *edid;
 
-return intel_ddc_get_modes(connector,
-   intel_gmbus_get_adapter(dev_priv,
-   intel_hdmi-&amp;gt;ddc_bus));
+edid = intel_hdmi_get_edid(connector);
+return intel_edid_get_modes(connector, edid);
 }
 
 static bool
 intel_hdmi_detect_audio(struct drm_connector *connector)
 {
-struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-struct drm_i915_private *dev_priv = connector-&amp;gt;dev-&amp;gt;dev_private;
 struct edid *edid;
 bool has_audio = false;
 
-edid = drm_get_edid(connector,
-    intel_gmbus_get_adapter(dev_priv,
-    intel_hdmi-&amp;gt;ddc_bus));
+edid = intel_hdmi_get_edid(connector);
 if (edid) {
 if (edid-&amp;gt;input &amp;amp; DRM_EDID_INPUT_DIGITAL)
 has_audio = drm_detect_monitor_audio(edid);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -580,8 +589,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; done:
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
+struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+
 drm_sysfs_connector_remove(connector);
 drm_connector_cleanup(connector);
+kfree(intel_hdmi-&amp;gt;cached_edid);
 kfree(connector);
 }
 
&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:47</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69603">
    <title>[PATCH 09/14] drm: don't poll forced connectors</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69603</link>
    <description>&lt;pre&gt;Otherwise if the detect callback reports a different state than what
the user forced (rather likely), we continously annoy userspace about
a hotplug uevent.

Signed-Off-by: Daniel Vetter &amp;lt;daniel.vetter&amp;lt; at &amp;gt;ffwll.ch&amp;gt;
---
 drivers/gpu/drm/drm_crtc_helper.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 87a45de..9214612 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -948,6 +948,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void output_poll_execute(struct work_struct *work)
 mutex_lock(&amp;amp;dev-&amp;gt;mode_config.mutex);
 list_for_each_entry(connector, &amp;amp;dev-&amp;gt;mode_config.connector_list, head) {
 
+/* Ignore forced connectors. */
+if (connector-&amp;gt;force)
+continue;
+
 /* Ignore HDP capable connectors and connectors where we don't
  * want any hotplug detection at all for polling. */
 if (!connector-&amp;gt;polled ||
&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:44</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69602">
    <title>[PATCH 08/14] drm: don't unnecessarily enable the polling work</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69602</link>
    <description>&lt;pre&gt;... by properly checking connector-&amp;gt;polled. This doesn't matter too
much because the polling work itself gets this slightly more right and
doesn't set repoll if there's nothing to do. But we can do better.

Signed-Off-by: Daniel Vetter &amp;lt;daniel.vetter&amp;lt; at &amp;gt;ffwll.ch&amp;gt;
---
 drivers/gpu/drm/drm_crtc_helper.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f17953e..87a45de 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -955,9 +955,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void output_poll_execute(struct work_struct *work)
     (connector-&amp;gt;polled &amp;amp; DRM_CONNECTOR_POLL_HPD))
 continue;
 
-else if (connector-&amp;gt;polled &amp;amp; (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
-repoll = true;
-
 old_status = connector-&amp;gt;status;
 /* if we are connected and don't want to poll for disconnect
    skip it */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1000,7 +997,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void drm_kms_helper_poll_enable(struct drm_device *dev)
 return;
 
 list_for_each_entry(connector, &amp;amp;dev-&amp;gt;mode_config.connector_list, head) {
-if (connector-&amp;gt;polled)
+if (connector-&amp;gt;polled &amp;amp; (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT))
 poll = true;
 }
 
&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:43</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69598">
    <title>[PATCH 04/14] drm/i915: set POLL_FORCE for sdvo outputs</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69598</link>
    <description>&lt;pre&gt;The detection function is simply too unreliable - it doesn't
properly pick up changes right away.

For now, just set the compat flag and ignore this, because on a
quick look fixing this properly is a very big fish to fry.

Signed-off-by: Daniel Vetter &amp;lt;daniel.vetter&amp;lt; at &amp;gt;ffwll.ch&amp;gt;
---
 drivers/gpu/drm/i915/intel_sdvo.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index a658207..fdc0574 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2012,6 +2012,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 connector-&amp;gt;base.base.doublescan_allowed = 0;
 connector-&amp;gt;base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
 
+connector-&amp;gt;base.base.polled |= DRM_CONNECTOR_POLL_FORCE;
+
 intel_connector_attach_encoder(&amp;amp;connector-&amp;gt;base, &amp;amp;encoder-&amp;gt;base);
 drm_sysfs_connector_add(&amp;amp;connector-&amp;gt;base.base);
 }
&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:39</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69597">
    <title>[PATCH 03/14] drm: introduce DRM_CONNECTOR_POLL_FORCE</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69597</link>
    <description>&lt;pre&gt;Useful for -&amp;gt;detect functions that have different behaviour if force
is set. This way probe_single_connector can avoid to do the expensive
edid dance on connectors where this is not needed.

I've checked through all drivers and set this flag everywhere where
the connector-&amp;gt;detect function has different behaviour if force is
set. For nouveau and radeon I've got lost in the code traces, so I've
set this flag unconditionally.

Note that we also need to update the poll_execute function to now
also ignore connectors which have only this new flag set.

v2: Change POLL_HDP checks so that they ignore POLL_FORCE for both the
poll and the hpd handling code.

v3: Sprinkle POLL_FORCE more liberally over drivers. It should be now
everywhere where a non-intel driver can return anything else than
connector_status_connected in its detect callback.

Signed-Off-by: Daniel Vetter &amp;lt;daniel.vetter&amp;lt; at &amp;gt;ffwll.ch&amp;gt;
---
 drivers/gpu/drm/drm_crtc_helper.c             |    6 ++++--
 drivers/gpu/drm/exynos/exynos_drm_connector.c |    2 ++
 drivers/gpu/drm/gma500/cdv_intel_crt.c        |    2 ++
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c       |    2 ++
 drivers/gpu/drm/gma500/mdfld_dsi_output.c     |    1 +
 drivers/gpu/drm/gma500/oaktrail_hdmi.c        |    2 ++
 drivers/gpu/drm/gma500/psb_intel_sdvo.c       |    2 ++
 drivers/gpu/drm/i915/intel_crt.c              |    3 ++-
 drivers/gpu/drm/i915/intel_tv.c               |    3 ++-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |    1 +
 drivers/gpu/drm/radeon/radeon_connectors.c    |    5 +++++
 drivers/gpu/drm/udl/udl_connector.c           |    2 ++
 drivers/staging/omapdrm/omap_connector.c      |    2 ++
 include/drm/drm_crtc.h                        |    4 ++++
 14 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index b1d643d..8ea1c1e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -944,7 +944,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void output_poll_execute(struct work_struct *work)
 
 /* Ignore HDP capable connectors and connectors where we don't
  * want any hotplug detection at all for polling. */
-if (!connector-&amp;gt;polled || connector-&amp;gt;polled == DRM_CONNECTOR_POLL_HPD)
+if (!connector-&amp;gt;polled ||
+    connector-&amp;gt;polled == DRM_CONNECTOR_POLL_FORCE ||
+    (connector-&amp;gt;polled &amp;amp; DRM_CONNECTOR_POLL_HPD))
 continue;
 
 else if (connector-&amp;gt;polled &amp;amp; (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1029,7 +1031,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void drm_helper_hpd_irq_event(struct drm_device *dev)
 list_for_each_entry(connector, &amp;amp;dev-&amp;gt;mode_config.connector_list, head) {
 
 /* Only handle HPD capable connectors. */
-if (connector-&amp;gt;polled != DRM_CONNECTOR_POLL_HPD)
+if (!(connector-&amp;gt;polled &amp;amp; DRM_CONNECTOR_POLL_HPD))
 continue;
 
 old_status = connector-&amp;gt;status;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index bf791fa..e5a8a27 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -327,6 +327,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 drm_connector_init(dev, connector, &amp;amp;exynos_connector_funcs, type);
 drm_connector_helper_add(connector, &amp;amp;exynos_connector_helper_funcs);
 
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 err = drm_sysfs_connector_add(connector);
 if (err)
 goto err_connector;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 1874220..e6b2e49 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -313,6 +313,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void cdv_intel_crt_init(struct drm_device *dev,
 drm_connector_helper_add(connector,
 &amp;amp;cdv_intel_crt_connector_helper_funcs);
 
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(connector);
 
 return;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 88b59d4..766aec8 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -373,6 +373,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void cdv_hdmi_init(struct drm_device *dev,
 hdmi_priv-&amp;gt;hdmi_i2c_adapter =
 &amp;amp;(psb_intel_encoder-&amp;gt;i2c_bus-&amp;gt;adapter);
 hdmi_priv-&amp;gt;dev = dev;
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(connector);
 return;
 
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 5675d93..0e97a91 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -604,6 +604,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void mdfld_dsi_output_init(struct drm_device *dev,
 dsi_config-&amp;gt;encoder = encoder;
 encoder-&amp;gt;base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
 INTEL_OUTPUT_MIPI2;
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
 drm_sysfs_connector_add(connector);
 return;
 
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index c10899c..23b8d52 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -349,6 +349,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void oaktrail_hdmi_init(struct drm_device *dev,
 connector-&amp;gt;display_info.subpixel_order = SubPixelHorizontalRGB;
 connector-&amp;gt;interlace_allowed = false;
 connector-&amp;gt;doublescan_allowed = false;
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(connector);
 
 return;
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index d39b15b..e86d8ba 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2028,6 +2028,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector,
 connector-&amp;gt;base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
 
 psb_intel_connector_attach_encoder(&amp;amp;connector-&amp;gt;base, &amp;amp;encoder-&amp;gt;base);
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(&amp;amp;connector-&amp;gt;base.base);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 75a70c4..a60d131 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -639,7 +639,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void intel_crt_init(struct drm_device *dev)
 if (I915_HAS_HOTPLUG(dev))
 connector-&amp;gt;polled = DRM_CONNECTOR_POLL_HPD;
 else
-connector-&amp;gt;polled = DRM_CONNECTOR_POLL_CONNECT;
+connector-&amp;gt;polled = DRM_CONNECTOR_POLL_CONNECT |
+    DRM_CONNECTOR_POLL_FORCE;
 
 /*
  * Configure the automatic hotplug detection stuff
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index a233a51..dad7d8e 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1614,7 +1614,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; intel_tv_init(struct drm_device *dev)
  *
  * More recent chipsets favour HDMI rather than integrated S-Video.
  */
-connector-&amp;gt;polled = DRM_CONNECTOR_POLL_CONNECT;
+connector-&amp;gt;polled = DRM_CONNECTOR_POLL_CONNECT |
+    DRM_CONNECTOR_POLL_FORCE;
 
 drm_connector_init(dev, connector, &amp;amp;intel_tv_connector_funcs,
    DRM_MODE_CONNECTOR_SVIDEO);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index fa86035..780d608 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1085,6 +1085,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; nouveau_connector_create(struct drm_device *dev, int index)
 if (ret == 0)
 connector-&amp;gt;polled = DRM_CONNECTOR_POLL_HPD;
 }
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
 
 drm_sysfs_connector_add(connector);
 return connector;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 2914c57..c64ecc9 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1830,6 +1830,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; radeon_add_atom_connector(struct drm_device *dev,
 } else
 connector-&amp;gt;polled = DRM_CONNECTOR_POLL_HPD;
 
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 connector-&amp;gt;display_info.subpixel_order = subpixel_order;
 drm_sysfs_connector_add(connector);
 return;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1987,6 +1989,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; radeon_add_legacy_connector(struct drm_device *dev,
 connector-&amp;gt;polled = DRM_CONNECTOR_POLL_CONNECT;
 } else
 connector-&amp;gt;polled = DRM_CONNECTOR_POLL_HPD;
+
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 connector-&amp;gt;display_info.subpixel_order = subpixel_order;
 drm_sysfs_connector_add(connector);
 if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index ba055e9..838dc71 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -131,6 +131,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
 drm_connector_init(dev, connector, &amp;amp;udl_connector_funcs, DRM_MODE_CONNECTOR_DVII);
 drm_connector_helper_add(connector, &amp;amp;udl_connector_helper_funcs);
 
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(connector);
 drm_mode_connector_attach_encoder(connector, encoder);
 
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c
index 5e2856c..bb8b134 100644
--- a/drivers/staging/omapdrm/omap_connector.c
+++ b/drivers/staging/omapdrm/omap_connector.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -358,6 +358,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_connector *omap_connector_init(struct drm_device *dev,
 connector-&amp;gt;interlace_allowed = 1;
 connector-&amp;gt;doublescan_allowed = 0;
 
+connector-&amp;gt;polled |= DRM_CONNECTOR_POLL_FORCE;
+
 drm_sysfs_connector_add(connector);
 
 return connector;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index d59bb7d..4417da2 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -514,6 +514,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; enum drm_connector_force {
 /* can cleanly poll for disconnections without flickering the screen */
 /* DACs should rarely do this without a lot of testing */
 #define DRM_CONNECTOR_POLL_DISCONNECT (1 &amp;lt;&amp;lt; 2)
+/* connector's -&amp;gt;detect function needs to be called when userspace forces
+ * detection. Should only be used if the detect function has special handling
+ * when force is set to avoid spurious re-reading of the edid. */
+#define DRM_CONNECTOR_POLL_FORCE (1 &amp;lt;&amp;lt; 3)
 
 #define MAX_ELD_BYTES128
 
&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:38</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69594">
    <title>[RFC] [PATCH 00/14] HPD/connector-polling rework</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69594</link>
    <description>&lt;pre&gt;Hi all,

I've got fed up with our sorry state of connector detection and rampant edid re
and rere-reading.

This patch series lays the groundwork in the drm helpers so that drivers can
avoid all this madness (at least on working hw) and properly cache the edid.

With the additional changes for drm/i915, the edid is now read _once_ per plug
event (or at boot-up/resume time). A further step would be to integrate the
hotplug handling into the driver itself and only call -&amp;gt;detect on the connectors
for which the irq handler received a hotplug event.

By adding POLL_FORCE drivers can get back the old behaviour of calling -&amp;gt;detect
every time probe_single_connector is called from userspace. I've splattered that
over all drivers where I've thought it might be required.

Note though that setting this doesn't avoid all regressions - the regular output
poll work will still ignore any connectors with POLL_HPD set. If a driver/hw
with broken hpd got away due to this, this will break stuff. But that should be
easy to fix by admitting the defeat and setting POLL_CONNECT|DISCONNECT
directly.

If other people want to convert over their drivers, the following steps are
required:
- Ensure that the connector status is unknown every time the driver could have
  missed a hpd event (e.g. after resume). drm_mode_config_reset will do that for
  you.
- Drop the POLL_FORCE flag for connectors where hdp is fully reliable.
- Implement edid caching - that's a nice way to figure out whether hpd is
  actually reliable, because if it isn't, this step will ensure that you get bug
  reports because the the edid won't ever get updated ;-)
- Optionally teach the driver some smarts about which specific connectors
  actually got a hotplug event. Mostly useful on cheap hw (like intel's) that
  can't distinguish between hdmi and dp without trying some aux channel
  transfers.

As you can guess from the patch series, I've discovered the hard way that i915
sdvo support is totally broken. Tested on most of the intel machines I have and
also quickly on my radeon hd5000.

Comments, flames, ideas and test reports highly welcome.

Cheers, Daniel

Daniel Vetter (14):
  drm: extract drm_kms_helper_hotplug_event
  drm: handle HDP and polled connectors separately
  drm: introduce DRM_CONNECTOR_POLL_FORCE
  drm/i915: set POLL_FORCE for sdvo outputs
  drm: properly init/reset connector status
  drm: kill unnecessary calls to connector-&amp;gt;detect
  drm: don't start the poll engine in probe_single_connector
  drm: don't unnecessarily enable the polling work
  drm: don't poll forced connectors
  drm/i915: cache crt edid
  drm/i915: cache dp edid
  drm/i915: cache hdmi edid
  drm/i915/sdvo: implement correct return value for -&amp;gt;get_modes
  drm/i915: s/mdelay/msleep/ in the sdvo detect function

 drivers/gpu/drm/drm_crtc.c                    |    6 ++-
 drivers/gpu/drm/drm_crtc_helper.c             |   76 ++++++++++++++++++-------
 drivers/gpu/drm/exynos/exynos_drm_connector.c |    2 +
 drivers/gpu/drm/gma500/cdv_intel_crt.c        |    2 +
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c       |    2 +
 drivers/gpu/drm/gma500/mdfld_dsi_output.c     |    1 +
 drivers/gpu/drm/gma500/oaktrail_hdmi.c        |    2 +
 drivers/gpu/drm/gma500/psb_intel_sdvo.c       |    2 +
 drivers/gpu/drm/i915/intel_crt.c              |   28 +++++++--
 drivers/gpu/drm/i915/intel_dp.c               |   47 +++++++--------
 drivers/gpu/drm/i915/intel_drv.h              |    2 +
 drivers/gpu/drm/i915/intel_hdmi.c             |   48 ++++++++++------
 drivers/gpu/drm/i915/intel_modes.c            |   18 +++++-
 drivers/gpu/drm/i915/intel_sdvo.c             |   45 +++++++++------
 drivers/gpu/drm/i915/intel_tv.c               |    3 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |    1 +
 drivers/gpu/drm/radeon/radeon_connectors.c    |    5 ++
 drivers/gpu/drm/udl/udl_connector.c           |    2 +
 drivers/staging/omapdrm/omap_connector.c      |    2 +
 include/drm/drm_crtc.h                        |    5 ++
 include/drm/drm_crtc_helper.h                 |    1 +
 21 files changed, 208 insertions(+), 92 deletions(-)

&lt;/pre&gt;</description>
    <dc:creator>Daniel Vetter</dc:creator>
    <dc:date>2012-05-24T19:26:35</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69593">
    <title>[Bug 50232] screen redraw is wrong in sauerbraten with the llvmcompiler</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69593</link>
    <description>&lt;pre&gt;https://bugs.freedesktop.org/show_bug.cgi?id=50232

--- Comment #2 from almos &amp;lt;aaalmosss&amp;lt; at &amp;gt;gmail.com&amp;gt; 2012-05-24 13:25:38 PDT ---
(In reply to comment #1)
The revert patch fixes the ghost image problem. The warning is still printed,
but the visuals seem to be good now.

&lt;/pre&gt;</description>
    <dc:creator>bugzilla-daemon&lt; at &gt;freedesktop.org</dc:creator>
    <dc:date>2012-05-24T20:25:38</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69592">
    <title>[Bug 50230] offset mapping in nexuiz results in bad texturing withthe llvm compiler</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69592</link>
    <description>&lt;pre&gt;https://bugs.freedesktop.org/show_bug.cgi?id=50230

--- Comment #10 from almos &amp;lt;aaalmosss&amp;lt; at &amp;gt;gmail.com&amp;gt; 2012-05-24 13:25:32 PDT ---
(In reply to comment #9)
Yes, the patch fixes it. I also tried the revert patch, and that fixes the
lightmap flickering.

&lt;/pre&gt;</description>
    <dc:creator>bugzilla-daemon&lt; at &gt;freedesktop.org</dc:creator>
    <dc:date>2012-05-24T20:25:32</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69591">
    <title>[RFC][PATCH 6/6] WIP drm/i915: "Atomic" modeset test implementation</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69591</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

Just a quick prototype to test the atomic modeset API. Implemented
via already existing non-atomic mechanisms internally.
---
 drivers/gpu/drm/i915/Makefile        |    1 +
 drivers/gpu/drm/i915/intel_atomic.c  |  788 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |    7 +
 3 files changed, 796 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_atomic.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 2e9268d..f97e7a4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -15,6 +15,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; i915-y := i915_drv.o i915_dma.o i915_irq.o \
   i915_gem_tiling.o \
   i915_sysfs.o \
   i915_trace_points.o \
+  intel_atomic.o \
   intel_display.o \
   intel_crt.o \
   intel_lvds.o \
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
new file mode 100644
index 0000000..a6643fd
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_atomic.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,788 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ */
+
+#include &amp;lt;drm/drmP.h&amp;gt;
+#include &amp;lt;drm/drm_crtc.h&amp;gt;
+
+static struct drm_property *prop_src_x;
+static struct drm_property *prop_src_y;
+static struct drm_property *prop_src_w;
+static struct drm_property *prop_src_h;
+static struct drm_property *prop_crtc_x;
+static struct drm_property *prop_crtc_y;
+static struct drm_property *prop_crtc_w;
+static struct drm_property *prop_crtc_h;
+static struct drm_property *prop_fb_id;
+static struct drm_property *prop_crtc_id;
+static struct drm_property *prop_mode_id;
+static struct drm_property *prop_connector_ids;
+/* FIXME must be per-CRTC */
+static struct drm_property_blob *blob_connector_ids;
+
+static uint32_t *connector_ids;
+
+struct intel_plane_state {
+struct drm_plane *plane;
+int32_t crtc_x, crtc_y;
+uint32_t crtc_w, crtc_h;
+uint32_t src_x, src_y, src_w, src_h;
+struct drm_framebuffer *fb;
+struct drm_crtc *crtc;
+uint32_t fb_id;
+uint32_t crtc_id;
+bool dirty;
+};
+
+struct intel_crtc_state {
+struct drm_crtc *crtc;
+struct drm_display_mode *mode;
+int x, y;
+struct drm_framebuffer *fb;
+uint32_t fb_id;
+bool mode_dirty;
+bool fb_dirty;
+bool active_dirty;
+unsigned int count_connectors;
+struct drm_connector **connectors;
+};
+
+struct intel_atomic_state {
+struct intel_plane_state plane[3];
+struct intel_crtc_state crtc[3];
+bool fbs_pinned;
+bool dirty;
+};
+
+static int populate_connectors(const struct drm_crtc *crtc,
+       struct drm_connector **connector_list)
+{
+struct drm_connector *connector;
+
+int i = 0;
+
+list_for_each_entry(connector, &amp;amp;crtc-&amp;gt;dev-&amp;gt;mode_config.connector_list, head) {
+if (!connector-&amp;gt;encoder || connector-&amp;gt;encoder-&amp;gt;crtc != crtc)
+continue;
+
+connector_list[i++] = connector;
+}
+
+return i;
+}
+
+static void *intel_atomic_begin(struct drm_device *dev, uint32_t flags)
+{
+struct intel_atomic_state *state;
+struct drm_plane *plane;
+struct drm_crtc *crtc;
+struct drm_connector **connector_ptr;
+int i;
+
+state = kzalloc(sizeof *state + dev-&amp;gt;mode_config.num_connector *
+sizeof(struct drm_connector *) * ARRAY_SIZE(state-&amp;gt;crtc), GFP_KERNEL);
+if (!state)
+return ERR_PTR(-ENOMEM);
+
+connector_ptr = (struct drm_connector **)(state + 1);
+
+i = 0;
+list_for_each_entry(crtc, &amp;amp;dev-&amp;gt;mode_config.crtc_list, head) {
+if (i &amp;gt;= ARRAY_SIZE(state-&amp;gt;crtc))
+break;
+
+state-&amp;gt;crtc[i].crtc = crtc;
+state-&amp;gt;crtc[i].mode = &amp;amp;crtc-&amp;gt;mode;
+state-&amp;gt;crtc[i].x = crtc-&amp;gt;x;
+state-&amp;gt;crtc[i].y = crtc-&amp;gt;y;
+state-&amp;gt;crtc[i].fb = crtc-&amp;gt;fb;
+state-&amp;gt;crtc[i].fb_id = crtc-&amp;gt;fb ? crtc-&amp;gt;fb-&amp;gt;base.id : 0;
+
+state-&amp;gt;crtc[i].count_connectors = populate_connectors(crtc, connector_ptr);
+state-&amp;gt;crtc[i].connectors = connector_ptr;
+connector_ptr += dev-&amp;gt;mode_config.num_connector;
+
+i++;
+}
+
+i = 0;
+list_for_each_entry(plane, &amp;amp;dev-&amp;gt;mode_config.plane_list, head) {
+if (i &amp;gt;= ARRAY_SIZE(state-&amp;gt;plane))
+break;
+
+state-&amp;gt;plane[i].plane = plane;
+state-&amp;gt;plane[i].crtc_x = plane-&amp;gt;crtc_x;
+state-&amp;gt;plane[i].crtc_y = plane-&amp;gt;crtc_y;
+state-&amp;gt;plane[i].crtc_w = plane-&amp;gt;crtc_w;
+state-&amp;gt;plane[i].crtc_h = plane-&amp;gt;crtc_h;
+state-&amp;gt;plane[i].src_x = plane-&amp;gt;src_x;
+state-&amp;gt;plane[i].src_y = plane-&amp;gt;src_y;
+state-&amp;gt;plane[i].src_w = plane-&amp;gt;src_w;
+state-&amp;gt;plane[i].src_h = plane-&amp;gt;src_h;
+state-&amp;gt;plane[i].fb = plane-&amp;gt;fb;
+state-&amp;gt;plane[i].fb_id = plane-&amp;gt;fb ? plane-&amp;gt;fb-&amp;gt;base.id : 0;
+state-&amp;gt;plane[i].crtc = plane-&amp;gt;crtc;
+state-&amp;gt;plane[i].crtc_id = plane-&amp;gt;crtc ? plane-&amp;gt;crtc-&amp;gt;base.id : 0;
+
+i++;
+}
+
+return state;
+}
+
+static int plane_set(struct intel_plane_state *state,
+     struct drm_property *prop,
+     uint64_t value)
+{
+struct drm_plane *plane = state-&amp;gt;plane;
+struct drm_mode_object *obj;
+
+if (!state)
+return -ENOENT;
+
+if (prop == prop_src_x) {
+if (state-&amp;gt;src_x == value)
+return 0;
+state-&amp;gt;src_x = value;
+} else if (prop == prop_src_y) {
+if (state-&amp;gt;src_y == value)
+return 0;
+state-&amp;gt;src_y = value;
+} else if (prop == prop_src_w) {
+if (state-&amp;gt;src_w == value)
+return 0;
+state-&amp;gt;src_w = value;
+} else if (prop == prop_src_h) {
+if (state-&amp;gt;src_h == value)
+return 0;
+state-&amp;gt;src_h = value;
+} else if (prop == prop_crtc_x) {
+if (state-&amp;gt;crtc_x == value)
+return 0;
+state-&amp;gt;crtc_x = value;
+} else if (prop == prop_crtc_y) {
+if (state-&amp;gt;crtc_y == value)
+return 0;
+state-&amp;gt;crtc_y = value;
+} else if (prop == prop_crtc_w) {
+if (state-&amp;gt;crtc_w == value)
+return 0;
+state-&amp;gt;crtc_w = value;
+} else if (prop == prop_crtc_h) {
+if (state-&amp;gt;crtc_h == value)
+return 0;
+state-&amp;gt;crtc_h = value;
+} else if (prop == prop_crtc_id) {
+struct drm_crtc *crtc = NULL;
+
+if (state-&amp;gt;crtc_id == value)
+return 0;
+
+if (value) {
+obj = drm_mode_object_find(plane-&amp;gt;dev, value, DRM_MODE_OBJECT_CRTC);
+if (!obj) {
+printk("Unknown CRTC ID %llu\n", value);
+return -ENOENT;
+}
+crtc = obj_to_crtc(obj);
+}
+
+state-&amp;gt;crtc = crtc;
+state-&amp;gt;crtc_id = value;
+} else if (prop == prop_fb_id) {
+struct drm_framebuffer *fb = NULL;
+
+if (state-&amp;gt;fb_id == value)
+return 0;
+
+if (value) {
+obj = drm_mode_object_find(plane-&amp;gt;dev, value, DRM_MODE_OBJECT_FB);
+if (!obj) {
+printk("Unknown framebuffer ID %llu\n", value);
+return -ENOENT;
+}
+fb = obj_to_fb(obj);
+}
+
+state-&amp;gt;fb = fb;
+state-&amp;gt;fb_id = value;
+} else
+return -ENOENT;
+
+state-&amp;gt;dirty = true;
+
+return 0;
+}
+
+static int crtc_set(struct intel_crtc_state *state,
+    struct drm_property *prop,
+    uint64_t value, void *blob_data)
+{
+struct drm_crtc *crtc = state-&amp;gt;crtc;
+struct drm_mode_object *obj;
+
+if (!state)
+return -ENOENT;
+
+if (prop == prop_src_x) {
+if (state-&amp;gt;x == value)
+return 0;
+state-&amp;gt;x = value;
+state-&amp;gt;mode_dirty = true;
+} else if (prop == prop_src_y) {
+if (state-&amp;gt;y == value)
+return 0;
+state-&amp;gt;y = value;
+state-&amp;gt;mode_dirty = true;
+} else if (prop == prop_mode_id) {
+struct drm_display_mode *mode = NULL;
+
+if (value) {
+obj = drm_mode_object_find(crtc-&amp;gt;dev, value, DRM_MODE_OBJECT_MODE);
+if (!obj) {
+printk("Unknown mode ID %llu\n", value);
+return -ENOENT;
+}
+mode = obj_to_mode(obj);
+}
+
+if (!state-&amp;gt;mode &amp;amp;&amp;amp; !mode)
+return 0;
+
+if (state-&amp;gt;mode &amp;amp;&amp;amp; mode &amp;amp;&amp;amp; !memcmp(state-&amp;gt;mode, mode, sizeof *mode))
+return 0;
+
+if (!state-&amp;gt;mode || !mode ||
+    state-&amp;gt;mode-&amp;gt;hdisplay != mode-&amp;gt;hdisplay ||
+    state-&amp;gt;mode-&amp;gt;vdisplay != mode-&amp;gt;vdisplay)
+state-&amp;gt;active_dirty = true;
+
+state-&amp;gt;mode = mode;
+state-&amp;gt;mode_dirty = true;
+} else if (prop == prop_fb_id) {
+struct drm_framebuffer *fb = NULL;
+
+if (state-&amp;gt;fb_id == value)
+return 0;
+
+if (value) {
+obj = drm_mode_object_find(crtc-&amp;gt;dev, value, DRM_MODE_OBJECT_FB);
+if (!obj) {
+printk("Unknown framebuffer ID %llu\n", value);
+return -ENOENT;
+}
+fb = obj_to_fb(obj);
+}
+
+if (state-&amp;gt;fb &amp;amp;&amp;amp; fb) {
+/* can we page flip? */
+if (state-&amp;gt;fb-&amp;gt;pixel_format == fb-&amp;gt;pixel_format &amp;amp;&amp;amp;
+    state-&amp;gt;fb-&amp;gt;offsets[0] == fb-&amp;gt;offsets[0] &amp;amp;&amp;amp;
+    state-&amp;gt;fb-&amp;gt;pitches[0] == fb-&amp;gt;pitches[0]) {
+state-&amp;gt;fb_id = value;
+state-&amp;gt;fb = obj_to_fb(obj);
+state-&amp;gt;fb_dirty = true;
+return 0;
+}
+}
+
+state-&amp;gt;fb_id = value;
+state-&amp;gt;fb = fb;
+state-&amp;gt;mode_dirty = true;
+} else if (prop == prop_connector_ids) {
+const uint32_t *new_conn = blob_data;
+uint32_t count_new_conn = value / sizeof(uint32_t);
+unsigned int i;
+
+if (value &amp;amp; 3)
+return -EINVAL;
+
+if (count_new_conn &amp;gt; crtc-&amp;gt;dev-&amp;gt;mode_config.num_connector)
+return -ERANGE;
+
+if (count_new_conn == state-&amp;gt;count_connectors) {
+for (i = 0; i &amp;lt; count_new_conn; i++) {
+if (state-&amp;gt;connectors[i]-&amp;gt;base.id != new_conn[i])
+break;
+}
+/* no change */
+if (i == count_new_conn)
+return 0;
+}
+
+if (!count_new_conn) {
+state-&amp;gt;count_connectors = 0;
+state-&amp;gt;mode_dirty = true;
+return 0;
+}
+
+for (i = 0; i &amp;lt; count_new_conn; i++) {
+obj = drm_mode_object_find(crtc-&amp;gt;dev, new_conn[i], DRM_MODE_OBJECT_CONNECTOR);
+if (!obj) {
+printk("Unknown connector ID %u\n", new_conn[i]);
+return -ENOENT;
+}
+
+state-&amp;gt;connectors[i] = obj_to_connector(obj);
+}
+state-&amp;gt;count_connectors = count_new_conn;
+state-&amp;gt;mode_dirty = true;
+} else
+return -ENOENT;
+
+return 0;
+}
+
+static struct intel_plane_state *get_plane_state(struct intel_atomic_state *state,
+ struct drm_plane *plane)
+{
+int i;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(state-&amp;gt;plane); i++)
+if (plane == state-&amp;gt;plane[i].plane)
+return &amp;amp;state-&amp;gt;plane[i];
+
+return NULL;
+}
+
+static struct intel_crtc_state *get_crtc_state(struct intel_atomic_state *state,
+       struct drm_crtc *crtc)
+{
+int i;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(state-&amp;gt;crtc); i++)
+if (crtc == state-&amp;gt;crtc[i].crtc)
+return &amp;amp;state-&amp;gt;crtc[i];
+
+return NULL;
+}
+
+static int intel_atomic_set(struct drm_device *dev,
+    void *state,
+    struct drm_mode_object *obj,
+    struct drm_property *prop,
+    uint64_t value, void *blob_data)
+{
+struct intel_atomic_state *s = state;
+int ret = -EINVAL;
+
+switch (obj-&amp;gt;type) {
+case DRM_MODE_OBJECT_PLANE:
+ret = plane_set(get_plane_state(s, obj_to_plane(obj)), prop, value);
+break;
+case DRM_MODE_OBJECT_CRTC:
+ret = crtc_set(get_crtc_state(s, obj_to_crtc(obj)), prop, value, blob_data);
+break;
+default:
+break;
+}
+
+kfree(blob_data);
+
+if (ret)
+return ret;
+
+s-&amp;gt;dirty = true;
+
+return 0;
+}
+
+static int check_plane(struct intel_plane_state *state)
+{
+/* FIXME check everything */
+
+return 0;
+}
+
+static void dirty_planes(struct intel_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+int i;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(state-&amp;gt;plane); i++) {
+if (state-&amp;gt;plane[i].crtc == crtc)
+state-&amp;gt;plane[i].dirty = true;
+}
+}
+
+static int check_crtc(struct intel_atomic_state *state,
+      struct intel_crtc_state *s)
+{
+/*
+ * Mark all planes on this CRTC as dirty if the active video
+ * area changed so that the planes will get reclipped correctly.
+ */
+if (s-&amp;gt;active_dirty)
+dirty_planes(state, s-&amp;gt;crtc);
+
+/* FIXME check mode and fb if dirty */
+
+return 0;
+}
+
+static int intel_atomic_check(struct drm_device *dev, void *state)
+{
+struct intel_atomic_state *s = state;
+int i;
+
+if (!s-&amp;gt;dirty)
+return 0;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;crtc); i++) {
+if (!s-&amp;gt;crtc[i].fb_dirty &amp;amp;&amp;amp; !s-&amp;gt;crtc[i].mode_dirty)
+continue;
+
+check_crtc(s, &amp;amp;s-&amp;gt;crtc[i]);
+}
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;plane); i++) {
+if (!s-&amp;gt;plane[i].dirty)
+continue;
+
+check_plane(&amp;amp;s-&amp;gt;plane[i]);
+}
+
+return 0;
+}
+
+static void update_plane_props(struct intel_plane_state *state)
+{
+struct drm_mode_object *obj = &amp;amp;state-&amp;gt;plane-&amp;gt;base;
+
+if (prop_src_x)
+drm_object_property_set_value(obj, prop_src_x, state-&amp;gt;src_x);
+if (prop_src_y)
+drm_object_property_set_value(obj, prop_src_y, state-&amp;gt;src_y);
+if (prop_src_w)
+drm_object_property_set_value(obj, prop_src_w, state-&amp;gt;src_w);
+if (prop_src_h)
+drm_object_property_set_value(obj, prop_src_h, state-&amp;gt;src_h);
+
+if (prop_crtc_x)
+drm_object_property_set_value(obj, prop_crtc_x, state-&amp;gt;crtc_x);
+if (prop_crtc_y)
+drm_object_property_set_value(obj, prop_crtc_y, state-&amp;gt;crtc_y);
+if (prop_crtc_w)
+drm_object_property_set_value(obj, prop_crtc_w, state-&amp;gt;crtc_w);
+if (prop_crtc_h)
+drm_object_property_set_value(obj, prop_crtc_h, state-&amp;gt;crtc_h);
+
+if (prop_fb_id)
+drm_object_property_set_value(obj, prop_fb_id, state-&amp;gt;fb_id);
+
+if (prop_crtc_id)
+drm_object_property_set_value(obj, prop_crtc_id, state-&amp;gt;crtc_id);
+}
+
+static void update_crtc_props(struct intel_crtc_state *state)
+{
+struct drm_mode_object *obj = &amp;amp;state-&amp;gt;crtc-&amp;gt;base;
+struct drm_device *dev = state-&amp;gt;crtc-&amp;gt;dev;
+unsigned int i;
+
+if (prop_src_x)
+drm_object_property_set_value(obj, prop_src_x, state-&amp;gt;x);
+if (prop_src_y)
+drm_object_property_set_value(obj, prop_src_y, state-&amp;gt;y);
+
+if (prop_fb_id)
+drm_object_property_set_value(obj, prop_fb_id, state-&amp;gt;fb_id);
+
+/* FIXME if mode is user specifiec via old setcrtc ioctl prop value should be -1 */
+if (prop_mode_id)
+drm_object_property_set_value(obj, prop_mode_id,
+      state-&amp;gt;mode ? state-&amp;gt;mode-&amp;gt;base.id : 0);
+
+if (!prop_connector_ids || !connector_ids)
+return;
+
+if (blob_connector_ids)
+drm_property_destroy_blob(dev, blob_connector_ids);
+
+for (i = 0; i &amp;lt; state-&amp;gt;count_connectors; i++)
+connector_ids[i] = state-&amp;gt;connectors[i]-&amp;gt;base.id;
+
+blob_connector_ids = drm_property_create_blob(dev,
+      state-&amp;gt;count_connectors * sizeof connector_ids[0],
+      connector_ids);
+if (!blob_connector_ids)
+drm_object_property_set_value(obj, prop_connector_ids,
+      blob_connector_ids-&amp;gt;base.id);
+else
+drm_object_property_set_value(obj, prop_connector_ids, 0);
+}
+
+static void update_props(struct intel_atomic_state *s)
+{
+int i;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;crtc); i++) {
+if (!s-&amp;gt;crtc[i].fb_dirty &amp;amp;&amp;amp; !s-&amp;gt;crtc[i].mode_dirty)
+continue;
+
+update_crtc_props(&amp;amp;s-&amp;gt;crtc[i]);
+}
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;plane); i++) {
+if (!s-&amp;gt;plane[i].dirty)
+continue;
+
+update_plane_props(&amp;amp;s-&amp;gt;plane[i]);
+}
+}
+
+static int update_crtc(struct intel_crtc_state *state)
+{
+struct drm_crtc *crtc = state-&amp;gt;crtc;
+struct drm_mode_set set;
+int i;
+
+if (!state-&amp;gt;mode_dirty)
+return crtc-&amp;gt;funcs-&amp;gt;page_flip(crtc, state-&amp;gt;fb, NULL);
+
+set.crtc = state-&amp;gt;crtc;
+set.x = state-&amp;gt;x;
+set.y = state-&amp;gt;y;
+set.mode = state-&amp;gt;mode;
+set.connectors = state-&amp;gt;connectors;
+set.num_connectors = state-&amp;gt;count_connectors;
+set.fb = state-&amp;gt;fb;
+
+#if 0
+printk("CRTC %u\n"
+       " x = %d\n"
+       " y = %d\n",
+       crtc-&amp;gt;base.id,
+       set.x,
+       set.y);
+
+if (set.mode) {
+printk(" mode %u\n"
+       "  hdisplay = %d\n"
+       "  hsync_start = %d\n"
+       "  hsync_end = %d\n"
+       "  htotal = %d\n"
+       "  hdisplay = %d\n"
+       "  hsync_start = %d\n"
+       "  hsync_end = %d\n"
+       "  htotal = %d\n"
+       "  clock = %d\n"
+       "  vrefresh = %d\n",
+       set.mode-&amp;gt;base.id,
+       set.mode-&amp;gt;hdisplay,
+       set.mode-&amp;gt;hsync_start,
+       set.mode-&amp;gt;hsync_end,
+       set.mode-&amp;gt;htotal,
+       set.mode-&amp;gt;vdisplay,
+       set.mode-&amp;gt;vsync_start,
+       set.mode-&amp;gt;vsync_end,
+       set.mode-&amp;gt;vtotal,
+       set.mode-&amp;gt;clock,
+       set.mode-&amp;gt;vrefresh);
+} else
+printk(" no mode\n");
+
+if (set.num_connectors) {
+printk(" connectors:");
+for (i = 0; i &amp;lt; set.num_connectors; i++)
+printk(" %u", set.connectors[i]-&amp;gt;base.id);
+printk("\n");
+} else
+printk(" no connectors\n");
+#endif
+
+return crtc-&amp;gt;funcs-&amp;gt;set_config(&amp;amp;set);
+}
+
+static int update_plane(struct intel_plane_state *state)
+{
+struct drm_plane *plane = state-&amp;gt;plane;
+int ret;
+
+if (state-&amp;gt;fb &amp;amp;&amp;amp; state-&amp;gt;crtc)
+ret = plane-&amp;gt;funcs-&amp;gt;update_plane(plane,
+ state-&amp;gt;crtc,
+ state-&amp;gt;fb,
+ state-&amp;gt;crtc_x,
+ state-&amp;gt;crtc_y,
+ state-&amp;gt;crtc_w,
+ state-&amp;gt;crtc_h,
+ state-&amp;gt;src_x,
+ state-&amp;gt;src_y,
+ state-&amp;gt;src_w,
+ state-&amp;gt;src_h);
+else
+ret = plane-&amp;gt;funcs-&amp;gt;disable_plane(plane);
+
+if (ret)
+return ret;
+
+plane-&amp;gt;fb = state-&amp;gt;fb;
+plane-&amp;gt;crtc = state-&amp;gt;crtc;
+plane-&amp;gt;crtc_x = state-&amp;gt;crtc_x;
+plane-&amp;gt;crtc_y = state-&amp;gt;crtc_y;
+plane-&amp;gt;crtc_w = state-&amp;gt;crtc_w;
+plane-&amp;gt;crtc_h = state-&amp;gt;crtc_h;
+plane-&amp;gt;src_x = state-&amp;gt;src_x;
+plane-&amp;gt;src_y = state-&amp;gt;src_y;
+plane-&amp;gt;src_w = state-&amp;gt;src_w;
+plane-&amp;gt;src_h = state-&amp;gt;src_h;
+
+return 0;
+}
+
+static int intel_atomic_commit(struct drm_device *dev, void *state)
+{
+struct intel_atomic_state *s = state;
+int i;
+int ret = 0;
+
+if (!s-&amp;gt;dirty)
+return 0;
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;crtc); i++) {
+if (!s-&amp;gt;crtc[i].mode_dirty)
+continue;
+
+//intel_disable_crtc();
+}
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;plane); i++) {
+if (!s-&amp;gt;plane[i].dirty)
+continue;
+
+ret = update_plane(&amp;amp;s-&amp;gt;plane[i]);
+if (ret)
+return ret;
+}
+
+for (i = 0; i &amp;lt; ARRAY_SIZE(s-&amp;gt;crtc); i++) {
+if (!s-&amp;gt;crtc[i].mode_dirty &amp;amp;&amp;amp; !s-&amp;gt;crtc[i].fb_dirty)
+continue;
+
+ret = update_crtc(&amp;amp;s-&amp;gt;crtc[i]);
+if (ret)
+return ret;
+}
+
+update_props(s);
+
+return ret;
+}
+
+static void intel_atomic_end(struct drm_device *dev, void *state)
+{
+kfree(state);
+}
+
+static const struct drm_atomic_funcs intel_atomic_funcs = {
+.begin = intel_atomic_begin,
+.set = intel_atomic_set,
+.check = intel_atomic_check,
+.commit = intel_atomic_commit,
+.end = intel_atomic_end,
+};
+
+int intel_atomic_init(struct drm_device *dev)
+{
+struct drm_crtc *crtc;
+struct drm_plane *plane;
+void *state;
+
+connector_ids = kcalloc(dev-&amp;gt;mode_config.num_connector, sizeof connector_ids[0], GFP_KERNEL);
+if (!connector_ids)
+return -ENOMEM;
+
+prop_src_x = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX);
+prop_src_y = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX);
+prop_src_w = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX);
+prop_src_h = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX);
+
+// fixme signed values needed
+prop_crtc_x = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX);
+prop_crtc_y = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX);
+prop_crtc_w = drm_property_create_range(dev, 0, "CRTC_W", 0, INT_MAX);
+prop_crtc_h = drm_property_create_range(dev, 0, "CRTC_H", 0, INT_MAX);
+
+prop_fb_id = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX);
+prop_crtc_id = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX);
+prop_mode_id = drm_property_create_range(dev, 0, "MODE_ID", 0, UINT_MAX);
+
+prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
+
+list_for_each_entry(plane, &amp;amp;dev-&amp;gt;mode_config.plane_list, head) {
+struct drm_mode_object *obj = &amp;amp;plane-&amp;gt;base;
+
+if (prop_src_x)
+drm_object_attach_property(obj, prop_src_x, 0);
+if (prop_src_y)
+drm_object_attach_property(obj, prop_src_y, 0);
+if (prop_src_w)
+drm_object_attach_property(obj, prop_src_w, 0);
+if (prop_src_h)
+drm_object_attach_property(obj, prop_src_h, 0);
+
+if (prop_crtc_x)
+drm_object_attach_property(obj, prop_crtc_x, 0);
+if (prop_crtc_y)
+drm_object_attach_property(obj, prop_crtc_y, 0);
+if (prop_crtc_w)
+drm_object_attach_property(obj, prop_crtc_w, 0);
+if (prop_crtc_h)
+drm_object_attach_property(obj, prop_crtc_h, 0);
+
+if (prop_fb_id)
+drm_object_attach_property(obj, prop_fb_id, 0);
+if (prop_crtc_id)
+drm_object_attach_property(obj, prop_crtc_id, 0);
+}
+
+list_for_each_entry(crtc, &amp;amp;dev-&amp;gt;mode_config.crtc_list, head) {
+struct drm_mode_object *obj = &amp;amp;crtc-&amp;gt;base;
+
+if (prop_src_x)
+drm_object_attach_property(obj, prop_src_x, 0);
+if (prop_src_y)
+drm_object_attach_property(obj, prop_src_y, 0);
+
+if (prop_fb_id)
+drm_object_attach_property(obj, prop_fb_id, 0);
+if (prop_mode_id)
+drm_object_attach_property(obj, prop_mode_id, 0);
+if (prop_connector_ids)
+drm_object_attach_property(obj, prop_connector_ids, 0);
+}
+
+dev-&amp;gt;driver-&amp;gt;atomic_funcs = &amp;amp;intel_atomic_funcs;
+
+/* quick way to pre-populate the properties... */
+state = intel_atomic_begin(dev, 0);
+if (state) {
+update_props(state);
+intel_atomic_end(dev, state);
+}
+
+return 0;
+}
+
+void intel_atomic_fini(struct drm_device *dev)
+{
+kfree(connector_ids);
+
+if (blob_connector_ids)
+drm_property_destroy_blob(dev, blob_connector_ids);
+
+drm_property_destroy(dev, prop_src_x);
+drm_property_destroy(dev, prop_src_y);
+drm_property_destroy(dev, prop_src_w);
+drm_property_destroy(dev, prop_src_h);
+
+drm_property_destroy(dev, prop_crtc_x);
+drm_property_destroy(dev, prop_crtc_y);
+drm_property_destroy(dev, prop_crtc_w);
+drm_property_destroy(dev, prop_crtc_h);
+
+drm_property_destroy(dev, prop_fb_id);
+drm_property_destroy(dev, prop_crtc_id);
+drm_property_destroy(dev, prop_mode_id);
+drm_property_destroy(dev, prop_connector_ids);
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index aec6cac..3ff6ae9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -7049,6 +7049,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void intel_modeset_init_hw(struct drm_device *dev)
 ivb_pch_pwm_override(dev);
 }
 
+void intel_atomic_init(struct drm_device *dev);
+void intel_atomic_fini(struct drm_device *dev);
+
 void intel_modeset_init(struct drm_device *dev)
 {
 struct drm_i915_private *dev_priv = dev-&amp;gt;dev_private;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -7103,6 +7106,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void intel_modeset_init(struct drm_device *dev)
 INIT_WORK(&amp;amp;dev_priv-&amp;gt;idle_work, intel_idle_update);
 setup_timer(&amp;amp;dev_priv-&amp;gt;idle_timer, intel_gpu_idle_timer,
     (unsigned long)dev);
+
+intel_atomic_init(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -7118,6 +7123,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void intel_modeset_cleanup(struct drm_device *dev)
 struct drm_crtc *crtc;
 struct intel_crtc *intel_crtc;
 
+intel_atomic_fini(dev);
+
 drm_kms_helper_poll_fini(dev);
 mutex_lock(&amp;amp;dev-&amp;gt;struct_mutex);
 
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:47</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69590">
    <title>[RFC][PATCH 5/6] WIP: drm: Atomic modeset ioctl</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69590</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

First draft.

The ioctl simply takes a list of object IDs and property IDs and their
values. For setting values to blob properties, the property value
indicates the length of the data, and the actual data is passed via
another blob pointer.

Detailed error reporting is missing, as is completion event support.
---
 drivers/gpu/drm/drm_crtc.c |  133 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_drv.c  |    1 +
 include/drm/drm.h          |    1 +
 include/drm/drmP.h         |    2 +
 include/drm/drm_crtc.h     |   12 ++++
 include/drm/drm_mode.h     |   14 +++++
 6 files changed, 163 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 958a4b0..0dc94c5 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4124,3 +4124,136 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
 return vscale;
 }
 EXPORT_SYMBOL(drm_calc_vscale);
+
+int drm_mode_atomic_ioctl(struct drm_device *dev,
+  void *data, struct drm_file *file_priv)
+{
+struct drm_mode_atomic *arg = data;
+uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg-&amp;gt;objs_ptr);
+uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg-&amp;gt;count_props_ptr);
+uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg-&amp;gt;props_ptr);
+uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg-&amp;gt;prop_values_ptr);
+uint64_t __user *blob_values_ptr = (uint64_t __user *)(unsigned long)(arg-&amp;gt;blob_values_ptr);
+unsigned int copied_objs = 0;
+unsigned int copied_props = 0;
+unsigned int copied_blobs = 0;
+void *state;
+int ret = 0;
+unsigned int i, j;
+
+if (!dev-&amp;gt;driver-&amp;gt;atomic_funcs ||
+    !dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;begin ||
+    !dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;set ||
+    !dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;check ||
+    !dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;commit ||
+    !dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;end)
+return -ENOSYS;
+
+if (arg-&amp;gt;flags &amp;amp; ~DRM_ATOMIC_TEST_ONLY)
+return -EINVAL;
+
+mutex_lock(&amp;amp;dev-&amp;gt;mode_config.mutex);
+
+state = dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;begin(dev, arg-&amp;gt;flags);
+if (IS_ERR(state)) {
+ret = PTR_ERR(state);
+goto unlock;
+}
+
+for (i = 0; i &amp;lt; arg-&amp;gt;count_objs; i++) {
+uint32_t obj_id, count_props;
+struct drm_mode_object *obj;
+
+if (get_user(obj_id, objs_ptr + copied_objs)) {
+ret = -EFAULT;
+goto out;
+}
+
+obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
+if (!obj || !obj-&amp;gt;properties) {
+ret = -ENOENT;
+goto out;
+}
+
+if (get_user(count_props, count_props_ptr + copied_objs)) {
+ret = -EFAULT;
+goto out;
+}
+
+copied_objs++;
+
+for (j = 0; j &amp;lt; count_props; j++) {
+uint32_t prop_id;
+uint64_t prop_value;
+struct drm_mode_object *prop_obj;
+struct drm_property *prop;
+void *blob_data = NULL;
+
+if (get_user(prop_id, props_ptr + copied_props)) {
+ret = -EFAULT;
+goto out;
+}
+
+if (!object_has_prop(obj, prop_id)) {
+ret = -EINVAL;
+goto out;
+}
+
+prop_obj = drm_mode_object_find(dev, prop_id, DRM_MODE_OBJECT_PROPERTY);
+if (!prop_obj) {
+ret = -ENOENT;
+goto out;
+}
+prop = obj_to_property(prop_obj);
+
+if (get_user(prop_value, prop_values_ptr + copied_props)) {
+ret = -EFAULT;
+goto out;
+}
+
+if (!drm_property_change_is_valid(prop, prop_value)) {
+ret = -EINVAL;
+goto out;
+}
+
+if (prop-&amp;gt;flags &amp;amp; DRM_MODE_PROP_BLOB &amp;amp;&amp;amp; prop_value) {
+blob_data = kmalloc(prop_value, GFP_KERNEL);
+if (!blob_data) {
+ret = -ENOMEM;
+goto out;
+}
+
+if (copy_from_user(blob_data, blob_values_ptr + copied_blobs, prop_value)) {
+kfree(blob_data);
+ret = -EFAULT;
+goto out;
+}
+
+copied_blobs++;
+}
+
+/* The driver will be in charge of blob_data from now on. */
+ret = dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;set(dev, state, obj, prop, prop_value, blob_data);
+if (ret)
+goto out;
+
+copied_props++;
+}
+}
+
+ret = dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;check(dev, state);
+if (ret)
+goto out;
+
+if (arg-&amp;gt;flags &amp;amp; DRM_ATOMIC_TEST_ONLY)
+goto out;
+
+ret = dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;commit(dev, state);
+
+ out:
+dev-&amp;gt;driver-&amp;gt;atomic_funcs-&amp;gt;end(dev, state);
+ unlock:
+mutex_unlock(&amp;amp;dev-&amp;gt;mode_config.mutex);
+
+return ret;
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 8a9d079..3e32c8a 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -166,6 +166,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct drm_ioctl_desc drm_ioctls[] = {
 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|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_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 #define DRM_CORE_IOCTL_COUNTARRAY_SIZE( drm_ioctls )
diff --git a/include/drm/drm.h b/include/drm/drm.h
index e51035a..b179169 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -732,6 +732,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_prime_handle {
 #define DRM_IOCTL_MODE_ADDFB2DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIESDRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
 #define DRM_IOCTL_MODE_OBJ_SETPROPERTYDRM_IOWR(0xBA, struct drm_mode_obj_set_property)
+#define DRM_IOCTL_MODE_ATOMICDRM_IOWR(0xBB, struct drm_mode_atomic)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 31ad880..7bff96d 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -964,6 +964,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_driver {
 
 /* List of devices hanging off this driver */
 struct list_head device_list;
+
+const struct drm_atomic_funcs *atomic_funcs;
 };
 
 #define DRM_MINOR_UNASSIGNED 0
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8b1f173..b3d6545 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1063,6 +1063,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
      struct drm_file *file_priv);
 extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
    struct drm_file *file_priv);
+extern int drm_mode_atomic_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
 
 extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
  int *bpp);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1099,4 +1101,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
 extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
    int min_vscale, int max_vscale);
 
+struct drm_atomic_funcs {
+void *(*begin)(struct drm_device *dev, uint32_t flags);
+int (*set)(struct drm_device *dev, void *state,
+   struct drm_mode_object *obj, struct drm_property *prop,
+   uint64_t value, void *blob_data);
+int (*check)(struct drm_device *dev, void *state);
+int (*commit)(struct drm_device *dev, void *state);
+void (*end)(struct drm_device *dev, void *state);
+};
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 5581980..ed776b4 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -459,4 +459,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_mode_destroy_dumb {
 uint32_t handle;
 };
 
+
+#define DRM_ATOMIC_TEST_ONLY (1&amp;lt;&amp;lt;0)
+
+/* FIXME come up with some sane error reporting mechanism? */
+struct drm_mode_atomic {
+__u32 flags;
+__u32 count_objs;
+__u64 objs_ptr;
+__u64 count_props_ptr;
+__u64 props_ptr;
+__u64 prop_values_ptr;
+__u64 blob_values_ptr;
+};
+
 #endif
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:46</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69589">
    <title>[RFC][PATCH 3/6] drm: Allow drm_mode_object_find() to look up anobject of any type</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69589</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

To avoid having to pass object types from userspace for atomic mode
setting ioctl, allow drm_mode_object_find() to look up an object of any
type. This will only work as long as the all object types share the ID
space.

Signed-off-by: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;
---
 drivers/gpu/drm/drm_crtc.c |    3 ++-
 include/drm/drm_crtc.h     |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index cc18ae6..9945e4b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -268,7 +268,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 
 mutex_lock(&amp;amp;dev-&amp;gt;mode_config.idr_mutex);
 obj = idr_find(&amp;amp;dev-&amp;gt;mode_config.crtc_idr, id);
-if (!obj || (obj-&amp;gt;type != type) || (obj-&amp;gt;id != id))
+if (!obj || (type != DRM_MODE_OBJECT_ANY &amp;amp;&amp;amp; obj-&amp;gt;type != type) ||
+    (obj-&amp;gt;id != id))
 obj = NULL;
 mutex_unlock(&amp;amp;dev-&amp;gt;mode_config.idr_mutex);
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 70554c3..8b1f173 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -47,6 +47,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_object_properties;
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
 #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
+#define DRM_MODE_OBJECT_ANY 0
 
 struct drm_mode_object {
 uint32_t id;
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:44</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69588">
    <title>[RFC][PATCH 4/6] drm: Refactor object property check code</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69588</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

Refactor the code to check whether an object has a specific property
to a new function.

Signed-off-by: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;
---
 drivers/gpu/drm/drm_crtc.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9945e4b..958a4b0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3301,6 +3301,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out:
 return ret;
 }
 
+static bool object_has_prop(const struct drm_mode_object *obj, u32 prop_id)
+{
+int i;
+
+if (!obj-&amp;gt;properties)
+return false;
+
+for (i = 0; i &amp;lt; obj-&amp;gt;properties-&amp;gt;count; i++)
+if (obj-&amp;gt;properties-&amp;gt;ids[i] == prop_id)
+return true;
+return false;
+}
+
 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
     struct drm_file *file_priv)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3309,7 +3322,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 struct drm_mode_object *prop_obj;
 struct drm_property *property;
 int ret = -EINVAL;
-int i;
 
 if (!drm_core_check_feature(dev, DRIVER_MODESET))
 return -EINVAL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3322,11 +3334,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 if (!arg_obj-&amp;gt;properties)
 goto out;
 
-for (i = 0; i &amp;lt; arg_obj-&amp;gt;properties-&amp;gt;count; i++)
-if (arg_obj-&amp;gt;properties-&amp;gt;ids[i] == arg-&amp;gt;prop_id)
-break;
-
-if (i == arg_obj-&amp;gt;properties-&amp;gt;count)
+if (!object_has_prop(arg_obj, arg-&amp;gt;prop_id))
 goto out;
 
 prop_obj = drm_mode_object_find(dev, arg-&amp;gt;prop_id,
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:45</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69587">
    <title>[RFC][PATCH 2/6] drm: Allow signed values for range properties</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69587</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

Treat a range property as signed when the unsigned minimum value is
larger than the unsigned maximum value.

Signed-off-by: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;
---
 drivers/gpu/drm/drm_crtc.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ce0f446..cc18ae6 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3143,14 +3143,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 
-static bool drm_property_change_is_valid(struct drm_property *property,
+static bool range_property_is_signed(const struct drm_property *property)
+{
+return property-&amp;gt;values[0] &amp;gt; property-&amp;gt;values[1];
+}
+
+static bool drm_property_change_is_valid(const struct drm_property *property,
  uint64_t value)
 {
 if (property-&amp;gt;flags &amp;amp; DRM_MODE_PROP_IMMUTABLE)
 return false;
 if (property-&amp;gt;flags &amp;amp; DRM_MODE_PROP_RANGE) {
-if (value &amp;lt; property-&amp;gt;values[0] || value &amp;gt; property-&amp;gt;values[1])
-return false;
+if (range_property_is_signed(property)) {
+if ((int64_t)value &amp;lt; (int64_t)property-&amp;gt;values[0] ||
+    (int64_t)value &amp;gt; (int64_t)property-&amp;gt;values[1])
+return false;
+} else {
+if (value &amp;lt; property-&amp;gt;values[0] || value &amp;gt; property-&amp;gt;values[1])
+return false;
+}
 return true;
 } else if (property-&amp;gt;flags &amp;amp; DRM_MODE_PROP_BITMASK) {
 int i;
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:43</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69586">
    <title>[RFC][PATCH 1/6] drm: Export drm_property_create_blob() anddrm_property_destroy_blob()</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69586</link>
    <description>&lt;pre&gt;From: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

Signed-off-by: Ville Syrjälä &amp;lt;ville.syrjala&amp;lt; at &amp;gt;linux.intel.com&amp;gt;
---
 drivers/gpu/drm/drm_crtc.c |    8 +++++---
 include/drm/drm_crtc.h     |    4 ++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6dafb99..ce0f446 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3044,8 +3044,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; done:
 return ret;
 }
 
-static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
-  void *data)
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
+   void *data)
 {
 struct drm_property_blob *blob;
 int ret;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3070,14 +3070,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
 list_add_tail(&amp;amp;blob-&amp;gt;head, &amp;amp;dev-&amp;gt;mode_config.property_blob_list);
 return blob;
 }
+EXPORT_SYMBOL(drm_property_create_blob);
 
-static void drm_property_destroy_blob(struct drm_device *dev,
+void drm_property_destroy_blob(struct drm_device *dev,
        struct drm_property_blob *blob)
 {
 drm_mode_object_put(dev, &amp;amp;blob-&amp;gt;base);
 list_del(&amp;amp;blob-&amp;gt;head);
 kfree(blob);
 }
+EXPORT_SYMBOL(drm_property_destroy_blob);
 
 int drm_mode_getblob_ioctl(struct drm_device *dev,
    void *data, struct drm_file *file_priv)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3261492..70554c3 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -952,6 +952,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
  const char *name,
  uint64_t min, uint64_t max);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
+extern struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+  int length, void *data);
+extern void drm_property_destroy_blob(struct drm_device *dev,
+      struct drm_property_blob *blob);
 extern int drm_property_add_enum(struct drm_property *property, int index,
  uint64_t value, const char *name);
 extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:42</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69585">
    <title>[RFC][PATCH 0/6] WIP: drm: Atomic mode setting idea</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69585</link>
    <description>&lt;pre&gt;This is some very early demo code for the atomic modesetting feature.

According to my current plan there would be just one ioctl. You simply feed
it an arbitrary list of object properties and the implementation will decice
how it can apply those (for example, whether it can complete the operation
truly atomically and/or asynchronously). So everything is a property. This
means the ioctl should be able to handle all future requirements just as
long as they can be expressed using properties that fit the current model.

In order to be able to feed connector lists, gamma tables, etc. the ioctl has
to accepts blobs. Just one blob per property for now. Not sure if that would be
enough. I also extended range propeties to support signed values.

The implementation has to provide five function pointers, and the
operation goes roughly like this:

ioctl() {
 funcs-&amp;gt;begin
 for_each_prop
 funcs-&amp;gt;set
 funcs-&amp;gt;check
 if (!check_only)
 funcs-&amp;gt;commit
 funcs-&amp;gt;end
}

The begin function allocates some kind of state object that will be used to
collect all the modified state from all the properties. The approach I used
in the demo implementation is to have the full state contained in the state
object, and then keep modifying it according to the new property values.
Finally the whole state gets checked as an atomic unit, and commited to
hardware if everything is OK.

The demo implementation I included does work, albeit not atomically and it
doesn't actually do any real state checking. It just calls the pre-existing
crtc helper and plane funcs from the commit hook.


I'm still pondering about the error reporting. One crazy idea would be to
return an error value for each modified property. That way the driver could
more accurately inform user space why the state is invalid.


Another missing thing is the completion event support. I'm thinking it
should perhaps just contain one timestamp, that being for the time when
the whole operation has completed. If the user wants accurate per-CRTC
timestamps he'd have to issue separate ioctls. The other approach would
be per-object timestamps. Or should it perhaps send out a separate event
for each modified object?

Also it would be nice if the completion event would contain a list of
framebuffer objects that became available when the operation completed.
That would be useful for triple buffering use, since you can't tell
beforehand which framebuffer gets replaced with the new one when you
issue flips faster than the refresh rate.

Some kind of event cookie could also be nice to have, to associate
each event with the ioctl request that spawned it.
&lt;/pre&gt;</description>
    <dc:creator>ville.syrjala&lt; at &gt;linux.intel.com</dc:creator>
    <dc:date>2012-05-24T20:16:41</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.video.dri.devel/69584">
    <title>Re: [PATCH 0/4] drm/i915: Make video sprites survive a modeset</title>
    <link>http://permalink.gmane.org/gmane.comp.video.dri.devel/69584</link>
    <description>&lt;pre&gt;
Mainly I just dislike incoherent behaviour.

One use case might be flipping to another framebuffer using the
setcrtc ioctl, in case the page flip ioctl isn't provided, or can't
be used. With the current code the result depends on various
implementation specific details like whether the driver implements
a set_base type of optimization in a certain way. From the user
space POV it's just a setcrtc ioctl, but there's no sensible way
to know whether the operation will destroy some unrelated state
or not.

&lt;/pre&gt;</description>
    <dc:creator>Ville Syrjälä</dc:creator>
    <dc:date>2012-05-24T19:34:26</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.comp.video.dri.devel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.comp.video.dri.devel</link>
  </textinput>
</rdf:RDF>

