Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / tegra / fb.c
index 9798a708032219adde9cfd6f75c75d937c704769..3513d12d5aa1447822a7ef57449799b1aff83df9 100644 (file)
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
        return false;
 }
 
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+                       struct tegra_bo_tiling *tiling)
 {
        struct tegra_fb *fb = to_tegra_fb(framebuffer);
 
-       if (fb->planes[0]->flags & TEGRA_BO_TILED)
-               return true;
+       /* TODO: handle YUV formats? */
+       *tiling = fb->planes[0]->tiling;
 
-       return false;
+       return 0;
 }
 
 static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
@@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
                             struct drm_fb_helper_surface_size *sizes)
 {
        struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
+       struct tegra_drm *tegra = helper->dev->dev_private;
        struct drm_device *drm = helper->dev;
        struct drm_mode_fb_cmd2 cmd = { 0 };
        unsigned int bytes_per_pixel;
@@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
 
        cmd.width = sizes->surface_width;
        cmd.height = sizes->surface_height;
-       cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+       cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
+                                 tegra->pitch_align);
        cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
                                                     sizes->surface_depth);
 
@@ -267,18 +270,13 @@ release:
        return err;
 }
 
-static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
        .fb_probe = tegra_fbdev_probe,
 };
 
-static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
-                                             unsigned int preferred_bpp,
-                                             unsigned int num_crtc,
-                                             unsigned int max_connectors)
+static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm)
 {
-       struct drm_fb_helper *helper;
        struct tegra_fbdev *fbdev;
-       int err;
 
        fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
        if (!fbdev) {
@@ -286,13 +284,23 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
                return ERR_PTR(-ENOMEM);
        }
 
-       fbdev->base.funcs = &tegra_fb_helper_funcs;
-       helper = &fbdev->base;
+       drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
+
+       return fbdev;
+}
+
+static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
+                           unsigned int preferred_bpp,
+                           unsigned int num_crtc,
+                           unsigned int max_connectors)
+{
+       struct drm_device *drm = fbdev->base.dev;
+       int err;
 
        err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
        if (err < 0) {
                dev_err(drm->dev, "failed to initialize DRM FB helper\n");
-               goto free;
+               return err;
        }
 
        err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
@@ -301,21 +309,17 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
                goto fini;
        }
 
-       drm_helper_disable_unused_functions(drm);
-
        err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
        if (err < 0) {
                dev_err(drm->dev, "failed to set initial configuration\n");
                goto fini;
        }
 
-       return fbdev;
+       return 0;
 
 fini:
        drm_fb_helper_fini(&fbdev->base);
-free:
-       kfree(fbdev);
-       return ERR_PTR(err);
+       return err;
 }
 
 static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
@@ -366,7 +370,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
 #endif
 };
 
-int tegra_drm_fb_init(struct drm_device *drm)
+int tegra_drm_fb_prepare(struct drm_device *drm)
 {
 #ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
@@ -381,8 +385,7 @@ int tegra_drm_fb_init(struct drm_device *drm)
        drm->mode_config.funcs = &tegra_drm_mode_funcs;
 
 #ifdef CONFIG_DRM_TEGRA_FBDEV
-       tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
-                                         drm->mode_config.num_connector);
+       tegra->fbdev = tegra_fbdev_create(drm);
        if (IS_ERR(tegra->fbdev))
                return PTR_ERR(tegra->fbdev);
 #endif
@@ -390,6 +393,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
        return 0;
 }
 
+int tegra_drm_fb_init(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_TEGRA_FBDEV
+       struct tegra_drm *tegra = drm->dev_private;
+       int err;
+
+       err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc,
+                              drm->mode_config.num_connector);
+       if (err < 0)
+               return err;
+#endif
+
+       return 0;
+}
+
 void tegra_drm_fb_exit(struct drm_device *drm)
 {
 #ifdef CONFIG_DRM_TEGRA_FBDEV