drm/i915: get_plane_config for i9xx v13
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 7 Mar 2014 16:57:49 +0000 (08:57 -0800)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 8 Mar 2014 10:31:41 +0000 (11:31 +0100)
Read out the current plane configuration at init time into a new
plane_config structure.  This allows us to track any existing
framebuffers attached to the plane and potentially re-use them in our
fbdev code for a smooth handoff.

v2: update for new pitch_for_width function (Jesse)
    comment how get_plane_config works with shared fbs (Jesse)
v3: s/ARGB/XRGB (Ville)
    use pipesrc width/height (Ville)
    fix fourcc comment (Bob)
    use drm_format_plane_cpp (Ville)
v4: use fb for tracking fb data object (Ville)
v5: fix up gen2 pitch limits (Ville)
v6: read out stride as well (Daniel)
v7: split out init ordering changes (Daniel)
    don't fetch config if !CONFIG_FB
v8: use proper height in get_plane_config (Chris)
v9: fix CONFIG_FB check for modular configs (Jani)
v10: add comment about stolen allocation stomping
v11: drop hw state readout hunk (Daniel)
v12: handle tiled BIOS fbs (Kristian)
     pull out common bits (Jesse)
v13: move fb obj alloc out to _init

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_display.c

index 482b8d4bd94a8a9c7c61a10487d734ad767657bf..4476497757798a863b7b373bab20a91d5618d52d 100644 (file)
@@ -5669,6 +5669,67 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
        pipe_config->port_clock = clock.dot / 5;
 }
 
+static void i9xx_get_plane_config(struct intel_crtc *crtc,
+                                 struct intel_plane_config *plane_config)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val, base, offset;
+       int pipe = crtc->pipe, plane = crtc->plane;
+       int fourcc, pixel_format;
+       int aligned_height;
+
+       plane_config->fb = kzalloc(sizeof(*plane_config->fb), GFP_KERNEL);
+       if (!plane_config->fb) {
+               DRM_DEBUG_KMS("failed to alloc fb\n");
+               return;
+       }
+
+       val = I915_READ(DSPCNTR(plane));
+
+       if (INTEL_INFO(dev)->gen >= 4)
+               if (val & DISPPLANE_TILED)
+                       plane_config->tiled = true;
+
+       pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
+       fourcc = intel_format_to_fourcc(pixel_format);
+       plane_config->fb->base.pixel_format = fourcc;
+       plane_config->fb->base.bits_per_pixel =
+               drm_format_plane_cpp(fourcc, 0) * 8;
+
+       if (INTEL_INFO(dev)->gen >= 4) {
+               if (plane_config->tiled)
+                       offset = I915_READ(DSPTILEOFF(plane));
+               else
+                       offset = I915_READ(DSPLINOFF(plane));
+               base = I915_READ(DSPSURF(plane)) & 0xfffff000;
+       } else {
+               base = I915_READ(DSPADDR(plane));
+       }
+       plane_config->base = base;
+
+       val = I915_READ(PIPESRC(pipe));
+       plane_config->fb->base.width = ((val >> 16) & 0xfff) + 1;
+       plane_config->fb->base.height = ((val >> 0) & 0xfff) + 1;
+
+       val = I915_READ(DSPSTRIDE(pipe));
+       plane_config->fb->base.pitches[0] = val & 0xffffff80;
+
+       aligned_height = intel_align_height(dev, plane_config->fb->base.height,
+                                           plane_config->tiled);
+
+       plane_config->size = ALIGN(plane_config->fb->base.pitches[0] *
+                                  aligned_height, PAGE_SIZE);
+
+       DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
+                     pipe, plane, plane_config->fb->base.width,
+                     plane_config->fb->base.height,
+                     plane_config->fb->base.bits_per_pixel, base,
+                     plane_config->fb->base.pitches[0],
+                     plane_config->size);
+
+}
+
 static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                                 struct intel_crtc_config *pipe_config)
 {
@@ -10828,6 +10889,7 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.update_plane = ironlake_update_plane;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_plane_config = i9xx_get_plane_config;
                dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
                dev_priv->display.crtc_enable = valleyview_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -10835,6 +10897,7 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.update_plane = i9xx_update_plane;
        } else {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_plane_config = i9xx_get_plane_config;
                dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;