drm/nv50/kms: move framebuffer wrangling out of common code

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index dd469db..b6e258f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -200,6 +200,10 @@
 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
 {
 	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+	struct nouveau_display *disp = nouveau_display(drm_fb->dev);
+
+	if (disp->fb_dtor)
+		disp->fb_dtor(drm_fb);
 
 	if (fb->nvbo)
 		drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
@@ -229,63 +233,24 @@
 			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct nouveau_bo *nvbo)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_display *disp = nouveau_display(dev);
 	struct drm_framebuffer *fb = &nv_fb->base;
 	int ret;
 
 	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
 	nv_fb->nvbo = nvbo;
 
-	if (nv_device(drm->device)->card_type >= NV_50) {
-		u32 tile_flags = nouveau_bo_tile_layout(nvbo);
-		if (tile_flags == 0x7a00 ||
-		    tile_flags == 0xfe00)
-			nv_fb->r_dma = NvEvoFB32;
-		else
-		if (tile_flags == 0x7000)
-			nv_fb->r_dma = NvEvoFB16;
-		else
-			nv_fb->r_dma = NvEvoVRAM_LP;
-
-		switch (fb->depth) {
-		case  8: nv_fb->r_format = 0x1e00; break;
-		case 15: nv_fb->r_format = 0xe900; break;
-		case 16: nv_fb->r_format = 0xe800; break;
-		case 24:
-		case 32: nv_fb->r_format = 0xcf00; break;
-		case 30: nv_fb->r_format = 0xd100; break;
-		default:
-			 NV_ERROR(drm, "unknown depth %d\n", fb->depth);
-			 return -EINVAL;
-		}
-
-		if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
-			NV_ERROR(drm, "framebuffer requires contiguous bo\n");
-			return -EINVAL;
-		}
-
-		if (nv_device(drm->device)->chipset == 0x50)
-			nv_fb->r_format |= (tile_flags << 8);
-
-		if (!tile_flags) {
-			if (nv_device(drm->device)->card_type < NV_D0)
-				nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
-			else
-				nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
-		} else {
-			u32 mode = nvbo->tile_mode;
-			if (nv_device(drm->device)->card_type >= NV_C0)
-				mode >>= 4;
-			nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
-		}
-	}
-
 	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
-	if (ret) {
+	if (ret)
 		return ret;
+
+	if (disp->fb_ctor) {
+		ret = disp->fb_ctor(fb);
+		if (ret)
+			disp->fb_dtor(fb);
 	}
 
-	return 0;
+	return ret;
 }
 
 static struct drm_framebuffer *
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index a71cf77..90426cb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -36,9 +36,13 @@
 	int  (*init)(struct drm_device *);
 	void (*fini)(struct drm_device *);
 
+	int  (*fb_ctor)(struct drm_framebuffer *);
+	void (*fb_dtor)(struct drm_framebuffer *);
+
 	struct nouveau_object *core;
 	struct nouveau_eventh **vblank;
 
+
 	struct drm_property *dithering_mode;
 	struct drm_property *dithering_depth;
 	struct drm_property *underscan_property;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 4c534b7..9e3a3de 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2169,8 +2169,71 @@
 }
 
 /******************************************************************************
+ * Framebuffer
+ *****************************************************************************/
+
+static void
+nv50_fb_dtor(struct drm_framebuffer *fb)
+{
+}
+
+static int
+nv50_fb_ctor(struct drm_framebuffer *fb)
+{
+	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+	struct nouveau_drm *drm = nouveau_drm(fb->dev);
+	struct nouveau_bo *nvbo = nv_fb->nvbo;
+	u32 tile_flags;
+
+	tile_flags = nouveau_bo_tile_layout(nvbo);
+	if (tile_flags == 0x7a00 ||
+	    tile_flags == 0xfe00)
+		nv_fb->r_dma = NvEvoFB32;
+	else
+	if (tile_flags == 0x7000)
+		nv_fb->r_dma = NvEvoFB16;
+	else
+		nv_fb->r_dma = NvEvoVRAM_LP;
+
+	if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
+		NV_ERROR(drm, "framebuffer requires contiguous bo\n");
+		return -EINVAL;
+	}
+
+	switch (fb->depth) {
+	case  8: nv_fb->r_format = 0x1e00; break;
+	case 15: nv_fb->r_format = 0xe900; break;
+	case 16: nv_fb->r_format = 0xe800; break;
+	case 24:
+	case 32: nv_fb->r_format = 0xcf00; break;
+	case 30: nv_fb->r_format = 0xd100; break;
+	default:
+		 NV_ERROR(drm, "unknown depth %d\n", fb->depth);
+		 return -EINVAL;
+	}
+
+	if (nv_device(drm->device)->chipset == 0x50)
+		nv_fb->r_format |= (tile_flags << 8);
+
+	if (!tile_flags) {
+		if (nv_device(drm->device)->card_type < NV_D0)
+			nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
+		else
+			nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
+	} else {
+		u32 mode = nvbo->tile_mode;
+		if (nv_device(drm->device)->card_type >= NV_C0)
+			mode >>= 4;
+		nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
+	}
+
+	return 0;
+}
+
+/******************************************************************************
  * Init
  *****************************************************************************/
+
 void
 nv50_display_fini(struct drm_device *dev)
 {
@@ -2233,6 +2296,8 @@
 	nouveau_display(dev)->dtor = nv50_display_destroy;
 	nouveau_display(dev)->init = nv50_display_init;
 	nouveau_display(dev)->fini = nv50_display_fini;
+	nouveau_display(dev)->fb_ctor = nv50_fb_ctor;
+	nouveau_display(dev)->fb_dtor = nv50_fb_dtor;
 	disp->core = nouveau_display(dev)->core;
 
 	/* small shared memory area we use for notifiers and semaphores */