drm/i915: add plane_config fetching infrastructure v2
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 7 Mar 2014 16:57:48 +0000 (08:57 -0800)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 8 Mar 2014 10:31:29 +0000 (11:31 +0100)
Early at init time, we can try to read out the plane config structure
and try to preserve it if possible.

v2: alloc fb obj at init time after fetching plane config

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

index 7b6dfdfb2d8d10e36207c6a88523b2324131e4bd..bfb537942dbef95c943be784c095c5087167dff8 100644 (file)
@@ -406,6 +406,7 @@ struct drm_i915_error_state {
 
 struct intel_connector;
 struct intel_crtc_config;
+struct intel_plane_config;
 struct intel_crtc;
 struct intel_limit;
 struct dpll;
@@ -444,6 +445,8 @@ struct drm_i915_display_funcs {
         * fills out the pipe-config with the hw state. */
        bool (*get_pipe_config)(struct intel_crtc *,
                                struct intel_crtc_config *);
+       void (*get_plane_config)(struct intel_crtc *,
+                                struct intel_plane_config *);
        int (*crtc_mode_set)(struct drm_crtc *crtc,
                             int x, int y,
                             struct drm_framebuffer *old_fb);
index 56edc840985658272c79a9e58d6be2a06efcbb49..482b8d4bd94a8a9c7c61a10487d734ad767657bf 100644 (file)
@@ -2047,6 +2047,70 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y,
        }
 }
 
+int intel_format_to_fourcc(int format)
+{
+       switch (format) {
+       case DISPPLANE_8BPP:
+               return DRM_FORMAT_C8;
+       case DISPPLANE_BGRX555:
+               return DRM_FORMAT_XRGB1555;
+       case DISPPLANE_BGRX565:
+               return DRM_FORMAT_RGB565;
+       default:
+       case DISPPLANE_BGRX888:
+               return DRM_FORMAT_XRGB8888;
+       case DISPPLANE_RGBX888:
+               return DRM_FORMAT_XBGR8888;
+       case DISPPLANE_BGRX101010:
+               return DRM_FORMAT_XRGB2101010;
+       case DISPPLANE_RGBX101010:
+               return DRM_FORMAT_XBGR2101010;
+       }
+}
+
+static void intel_alloc_plane_obj(struct intel_crtc *crtc,
+                                 struct intel_plane_config *plane_config)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_gem_object *obj = NULL;
+       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+       u32 base = plane_config->base;
+
+       if (!plane_config->fb)
+               return;
+
+       obj = i915_gem_object_create_stolen_for_preallocated(dev, base, base,
+                                                            plane_config->size);
+       if (!obj)
+               return;
+
+       if (plane_config->tiled) {
+               obj->tiling_mode = I915_TILING_X;
+               obj->stride = plane_config->fb->base.pitches[0];
+       }
+
+       mode_cmd.pixel_format = plane_config->fb->base.pixel_format;
+       mode_cmd.width = plane_config->fb->base.width;
+       mode_cmd.height = plane_config->fb->base.height;
+       mode_cmd.pitches[0] = plane_config->fb->base.pitches[0];
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (intel_framebuffer_init(dev, plane_config->fb, &mode_cmd, obj)) {
+               DRM_DEBUG_KMS("intel fb init failed\n");
+               goto out_unref_obj;
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG_KMS("plane fb obj %p\n", plane_config->fb->obj);
+       return;
+
+out_unref_obj:
+       drm_gem_object_unreference(&obj->base);
+       mutex_unlock(&dev->struct_mutex);
+
+}
+
 static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                             int x, int y)
 {
@@ -11033,6 +11097,7 @@ void intel_modeset_init(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int sprite, ret;
        enum pipe pipe;
+       struct intel_crtc *crtc;
 
        drm_mode_config_init(dev);
 
@@ -11095,6 +11160,33 @@ void intel_modeset_init(struct drm_device *dev)
        mutex_lock(&dev->mode_config.mutex);
        intel_modeset_setup_hw_state(dev, false);
        mutex_unlock(&dev->mode_config.mutex);
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+                           base.head) {
+               if (!crtc->active)
+                       continue;
+
+#if IS_ENABLED(CONFIG_FB)
+               /*
+                * We don't have a good way of freeing the buffer w/o the FB
+                * layer owning it...
+                * Note that reserving the BIOS fb up front prevents us
+                * from stuffing other stolen allocations like the ring
+                * on top.  This prevents some ugliness at boot time, and
+                * can even allow for smooth boot transitions if the BIOS
+                * fb is large enough for the active pipe configuration.
+                */
+               if (dev_priv->display.get_plane_config) {
+                       dev_priv->display.get_plane_config(crtc,
+                                                          &crtc->plane_config);
+                       /*
+                        * If the fb is shared between multiple heads, we'll
+                        * just get the first one.
+                        */
+                       intel_alloc_plane_obj(crtc, &crtc->plane_config);
+               }
+#endif
+       }
 }
 
 static void
index 9c7090590776b98131d0681f9c89ae5ccf03038a..48af57bbc73dfb346070a24f2406cc9ba91d1693 100644 (file)
@@ -218,6 +218,13 @@ typedef struct dpll {
        int     p;
 } intel_clock_t;
 
+struct intel_plane_config {
+       struct intel_framebuffer *fb; /* ends up managed by intel_fbdev.c */
+       bool tiled;
+       int size;
+       u32 base;
+};
+
 struct intel_crtc_config {
        /**
         * quirks - bitfield with hw state readout quirks
@@ -366,6 +373,7 @@ struct intel_crtc {
        int16_t cursor_width, cursor_height;
        bool cursor_visible;
 
+       struct intel_plane_config plane_config;
        struct intel_crtc_config config;
        struct intel_crtc_config *new_config;
        bool new_enabled;
@@ -740,6 +748,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
                                 struct intel_crtc_config *pipe_config);
+int intel_format_to_fourcc(int format);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);