aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-09 14:10:19 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-08-09 15:12:56 -0400
commit8a42364701d6860e51d53bbcbe3c84fe93816861 (patch)
treeca75f4ef70396f529f6c0b9209c234acd4e243f5
parentab0af559d34b6817768c1720859aef7d7009ee57 (diff)
drm/nv50/kms: create ctxdma objects for framebuffers as required
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h3
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c282
4 files changed, 126 insertions, 163 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index a0534489d23f..a7cbbe9d5d8d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -46,7 +46,7 @@ struct nouveau_crtc {
46 int cpp; 46 int cpp;
47 bool blanked; 47 bool blanked;
48 uint32_t offset; 48 uint32_t offset;
49 uint32_t tile_flags; 49 uint32_t handle;
50 } fb; 50 } fb;
51 51
52 struct { 52 struct {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 90426cb07c5e..a21fd2dbeb18 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -9,7 +9,7 @@ struct nouveau_framebuffer {
9 struct drm_framebuffer base; 9 struct drm_framebuffer base;
10 struct nouveau_bo *nvbo; 10 struct nouveau_bo *nvbo;
11 struct nouveau_vma vma; 11 struct nouveau_vma vma;
12 u32 r_dma; 12 u32 r_handle;
13 u32 r_format; 13 u32 r_format;
14 u32 r_pitch; 14 u32 r_pitch;
15}; 15};
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index dc0e0c5cadb4..30e46cc4fbfd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -79,9 +79,6 @@ enum {
79 79
80 /* G80+ display objects */ 80 /* G80+ display objects */
81 NvEvoVRAM = 0x01000000, 81 NvEvoVRAM = 0x01000000,
82 NvEvoFB16 = 0x01000001,
83 NvEvoFB32 = 0x01000002,
84 NvEvoVRAM_LP = 0x01000003,
85 NvEvoSync = 0xcafe0000 82 NvEvoSync = 0xcafe0000
86}; 83};
87 84
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 9e3a3dec6b47..61fc682accdd 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -149,125 +149,6 @@ nv50_dmac_destroy(struct nouveau_object *core, struct nv50_dmac *dmac)
149} 149}
150 150
151static int 151static int
152nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
153{
154 struct nouveau_fb *pfb = nouveau_fb(core);
155 struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
156 struct nouveau_object *object;
157 int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
158 NV_DMA_IN_MEMORY_CLASS,
159 &(struct nv_dma_class) {
160 .flags = NV_DMA_TARGET_VRAM |
161 NV_DMA_ACCESS_RDWR,
162 .start = 0,
163 .limit = pfb->ram->size - 1,
164 .conf0 = NV50_DMA_CONF0_ENABLE |
165 NV50_DMA_CONF0_PART_256,
166 }, sizeof(struct nv_dma_class), &object);
167 if (ret)
168 return ret;
169
170 ret = nouveau_object_new(client, parent, NvEvoFB16,
171 NV_DMA_IN_MEMORY_CLASS,
172 &(struct nv_dma_class) {
173 .flags = NV_DMA_TARGET_VRAM |
174 NV_DMA_ACCESS_RDWR,
175 .start = 0,
176 .limit = pfb->ram->size - 1,
177 .conf0 = NV50_DMA_CONF0_ENABLE | 0x70 |
178 NV50_DMA_CONF0_PART_256,
179 }, sizeof(struct nv_dma_class), &object);
180 if (ret)
181 return ret;
182
183 ret = nouveau_object_new(client, parent, NvEvoFB32,
184 NV_DMA_IN_MEMORY_CLASS,
185 &(struct nv_dma_class) {
186 .flags = NV_DMA_TARGET_VRAM |
187 NV_DMA_ACCESS_RDWR,
188 .start = 0,
189 .limit = pfb->ram->size - 1,
190 .conf0 = NV50_DMA_CONF0_ENABLE | 0x7a |
191 NV50_DMA_CONF0_PART_256,
192 }, sizeof(struct nv_dma_class), &object);
193 return ret;
194}
195
196static int
197nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
198{
199 struct nouveau_fb *pfb = nouveau_fb(core);
200 struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
201 struct nouveau_object *object;
202 int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
203 NV_DMA_IN_MEMORY_CLASS,
204 &(struct nv_dma_class) {
205 .flags = NV_DMA_TARGET_VRAM |
206 NV_DMA_ACCESS_RDWR,
207 .start = 0,
208 .limit = pfb->ram->size - 1,
209 .conf0 = NVC0_DMA_CONF0_ENABLE,
210 }, sizeof(struct nv_dma_class), &object);
211 if (ret)
212 return ret;
213
214 ret = nouveau_object_new(client, parent, NvEvoFB16,
215 NV_DMA_IN_MEMORY_CLASS,
216 &(struct nv_dma_class) {
217 .flags = NV_DMA_TARGET_VRAM |
218 NV_DMA_ACCESS_RDWR,
219 .start = 0,
220 .limit = pfb->ram->size - 1,
221 .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
222 }, sizeof(struct nv_dma_class), &object);
223 if (ret)
224 return ret;
225
226 ret = nouveau_object_new(client, parent, NvEvoFB32,
227 NV_DMA_IN_MEMORY_CLASS,
228 &(struct nv_dma_class) {
229 .flags = NV_DMA_TARGET_VRAM |
230 NV_DMA_ACCESS_RDWR,
231 .start = 0,
232 .limit = pfb->ram->size - 1,
233 .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
234 }, sizeof(struct nv_dma_class), &object);
235 return ret;
236}
237
238static int
239nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
240{
241 struct nouveau_fb *pfb = nouveau_fb(core);
242 struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
243 struct nouveau_object *object;
244 int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
245 NV_DMA_IN_MEMORY_CLASS,
246 &(struct nv_dma_class) {
247 .flags = NV_DMA_TARGET_VRAM |
248 NV_DMA_ACCESS_RDWR,
249 .start = 0,
250 .limit = pfb->ram->size - 1,
251 .conf0 = NVD0_DMA_CONF0_ENABLE |
252 NVD0_DMA_CONF0_PAGE_LP,
253 }, sizeof(struct nv_dma_class), &object);
254 if (ret)
255 return ret;
256
257 ret = nouveau_object_new(client, parent, NvEvoFB32,
258 NV_DMA_IN_MEMORY_CLASS,
259 &(struct nv_dma_class) {
260 .flags = NV_DMA_TARGET_VRAM |
261 NV_DMA_ACCESS_RDWR,
262 .start = 0,
263 .limit = pfb->ram->size - 1,
264 .conf0 = NVD0_DMA_CONF0_ENABLE | 0xfe |
265 NVD0_DMA_CONF0_PAGE_LP,
266 }, sizeof(struct nv_dma_class), &object);
267 return ret;
268}
269
270static int
271nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head, 152nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
272 void *data, u32 size, u64 syncbuf, 153 void *data, u32 size, u64 syncbuf,
273 struct nv50_dmac *dmac) 154 struct nv50_dmac *dmac)
@@ -322,13 +203,6 @@ nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
322 if (ret) 203 if (ret)
323 return ret; 204 return ret;
324 205
325 if (nv_device(core)->card_type < NV_C0)
326 ret = nv50_dmac_create_fbdma(core, dmac->base.handle);
327 else
328 if (nv_device(core)->card_type < NV_D0)
329 ret = nvc0_dmac_create_fbdma(core, dmac->base.handle);
330 else
331 ret = nvd0_dmac_create_fbdma(core, dmac->base.handle);
332 return ret; 206 return ret;
333} 207}
334 208
@@ -375,7 +249,7 @@ struct nv50_disp {
375 struct nouveau_object *core; 249 struct nouveau_object *core;
376 struct nv50_mast mast; 250 struct nv50_mast mast;
377 251
378 u32 modeset; 252 struct list_head fbdma;
379 253
380 struct nouveau_bo *sync; 254 struct nouveau_bo *sync;
381}; 255};
@@ -611,7 +485,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
611 evo_data(push, 0x00000000); 485 evo_data(push, 0x00000000);
612 evo_data(push, 0x00000000); 486 evo_data(push, 0x00000000);
613 evo_mthd(push, 0x00c0, 1); 487 evo_mthd(push, 0x00c0, 1);
614 evo_data(push, nv_fb->r_dma); 488 evo_data(push, nv_fb->r_handle);
615 evo_mthd(push, 0x0110, 2); 489 evo_mthd(push, 0x0110, 2);
616 evo_data(push, 0x00000000); 490 evo_data(push, 0x00000000);
617 evo_data(push, 0x00000000); 491 evo_data(push, 0x00000000);
@@ -846,7 +720,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
846 evo_data(push, (y << 16) | x); 720 evo_data(push, (y << 16) | x);
847 if (nv50_vers(mast) > NV50_DISP_MAST_CLASS) { 721 if (nv50_vers(mast) > NV50_DISP_MAST_CLASS) {
848 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1); 722 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
849 evo_data(push, nvfb->r_dma); 723 evo_data(push, nvfb->r_handle);
850 } 724 }
851 } else { 725 } else {
852 evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); 726 evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
@@ -855,7 +729,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
855 evo_data(push, (fb->height << 16) | fb->width); 729 evo_data(push, (fb->height << 16) | fb->width);
856 evo_data(push, nvfb->r_pitch); 730 evo_data(push, nvfb->r_pitch);
857 evo_data(push, nvfb->r_format); 731 evo_data(push, nvfb->r_format);
858 evo_data(push, nvfb->r_dma); 732 evo_data(push, nvfb->r_handle);
859 evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1); 733 evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
860 evo_data(push, (y << 16) | x); 734 evo_data(push, (y << 16) | x);
861 } 735 }
@@ -867,7 +741,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
867 evo_kick(push, mast); 741 evo_kick(push, mast);
868 } 742 }
869 743
870 nv_crtc->fb.tile_flags = nvfb->r_dma; 744 nv_crtc->fb.handle = nvfb->r_handle;
871 return 0; 745 return 0;
872} 746}
873 747
@@ -999,14 +873,14 @@ nv50_crtc_commit(struct drm_crtc *crtc)
999 if (push) { 873 if (push) {
1000 if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) { 874 if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
1001 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1); 875 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
1002 evo_data(push, NvEvoVRAM_LP); 876 evo_data(push, nv_crtc->fb.handle);
1003 evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2); 877 evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
1004 evo_data(push, 0xc0000000); 878 evo_data(push, 0xc0000000);
1005 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); 879 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
1006 } else 880 } else
1007 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { 881 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
1008 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1); 882 evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
1009 evo_data(push, nv_crtc->fb.tile_flags); 883 evo_data(push, nv_crtc->fb.handle);
1010 evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2); 884 evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
1011 evo_data(push, 0xc0000000); 885 evo_data(push, 0xc0000000);
1012 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); 886 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
@@ -1014,7 +888,7 @@ nv50_crtc_commit(struct drm_crtc *crtc)
1014 evo_data(push, NvEvoVRAM); 888 evo_data(push, NvEvoVRAM);
1015 } else { 889 } else {
1016 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); 890 evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
1017 evo_data(push, nv_crtc->fb.tile_flags); 891 evo_data(push, nv_crtc->fb.handle);
1018 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4); 892 evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
1019 evo_data(push, 0x83000000); 893 evo_data(push, 0x83000000);
1020 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); 894 evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
@@ -2172,6 +2046,97 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
2172 * Framebuffer 2046 * Framebuffer
2173 *****************************************************************************/ 2047 *****************************************************************************/
2174 2048
2049struct nv50_fbdma {
2050 struct list_head head;
2051 u32 name;
2052};
2053
2054static void
2055nv50_fbdma_fini(struct drm_device *dev, struct nv50_fbdma *fbdma)
2056{
2057 struct nv50_disp *disp = nv50_disp(dev);
2058 struct nv50_mast *mast = nv50_mast(dev);
2059 struct nouveau_object *client = nv_pclass(disp->core, NV_CLIENT_CLASS);
2060 struct drm_crtc *crtc;
2061
2062 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
2063 struct nv50_sync *sync = nv50_sync(crtc);
2064 nouveau_object_del(client, sync->base.base.handle, fbdma->name);
2065 }
2066
2067 nouveau_object_del(client, mast->base.base.handle, fbdma->name);
2068 list_del(&fbdma->head);
2069 kfree(fbdma);
2070}
2071
2072static int
2073nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kind)
2074{
2075 struct nouveau_drm *drm = nouveau_drm(dev);
2076 struct nv50_disp *disp = nv50_disp(dev);
2077 struct nv50_mast *mast = nv50_mast(dev);
2078 struct nouveau_object *client = nv_pclass(disp->core, NV_CLIENT_CLASS);
2079 struct nouveau_object *object;
2080 struct nv_dma_class args;
2081 struct nv50_fbdma *fbdma;
2082 struct drm_crtc *crtc;
2083 int ret;
2084
2085 list_for_each_entry(fbdma, &disp->fbdma, head) {
2086 if (fbdma->name == name)
2087 return 0;
2088 }
2089
2090 fbdma = kzalloc(sizeof(*fbdma), GFP_KERNEL);
2091 if (!fbdma)
2092 return -ENOMEM;
2093 list_add(&fbdma->head, &disp->fbdma);
2094 fbdma->name = name;
2095
2096 args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
2097 args.start = offset;
2098 args.limit = offset + length - 1;
2099 args.conf0 = kind;
2100
2101 if (nv_device(drm->device)->chipset < 0x80) {
2102 args.conf0 = NV50_DMA_CONF0_ENABLE;
2103 args.conf0 |= NV50_DMA_CONF0_PART_256;
2104 } else
2105 if (nv_device(drm->device)->chipset < 0xc0) {
2106 args.conf0 |= NV50_DMA_CONF0_ENABLE;
2107 args.conf0 |= NV50_DMA_CONF0_PART_256;
2108 } else
2109 if (nv_device(drm->device)->chipset < 0xd0) {
2110 args.conf0 |= NVC0_DMA_CONF0_ENABLE;
2111 } else {
2112 args.conf0 |= NVD0_DMA_CONF0_ENABLE;
2113 args.conf0 |= NVD0_DMA_CONF0_PAGE_LP;
2114 }
2115
2116 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
2117 struct nv50_sync *sync = nv50_sync(crtc);
2118 ret = nouveau_object_new(client, sync->base.base.handle,
2119 fbdma->name, NV_DMA_IN_MEMORY_CLASS,
2120 &args, sizeof(args), &object);
2121 if (ret) {
2122 printk(KERN_ERR "fail %d %08x %d\n", nv50_head(crtc)->base.index, fbdma->name, ret);
2123 nv50_fbdma_fini(dev, fbdma);
2124 return ret;
2125 }
2126 }
2127
2128 ret = nouveau_object_new(client, mast->base.base.handle, fbdma->name,
2129 NV_DMA_IN_MEMORY_CLASS, &args, sizeof(args),
2130 &object);
2131 if (ret) {
2132 printk(KERN_ERR "fail %08x %d\n", fbdma->name, ret);
2133 nv50_fbdma_fini(dev, fbdma);
2134 return ret;
2135 }
2136
2137 return 0;
2138}
2139
2175static void 2140static void
2176nv50_fb_dtor(struct drm_framebuffer *fb) 2141nv50_fb_dtor(struct drm_framebuffer *fb)
2177{ 2142{
@@ -2183,23 +2148,19 @@ nv50_fb_ctor(struct drm_framebuffer *fb)
2183 struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); 2148 struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
2184 struct nouveau_drm *drm = nouveau_drm(fb->dev); 2149 struct nouveau_drm *drm = nouveau_drm(fb->dev);
2185 struct nouveau_bo *nvbo = nv_fb->nvbo; 2150 struct nouveau_bo *nvbo = nv_fb->nvbo;
2186 u32 tile_flags; 2151 struct nv50_disp *disp = nv50_disp(fb->dev);
2187 2152 struct nouveau_fb *pfb = nouveau_fb(drm->device);
2188 tile_flags = nouveau_bo_tile_layout(nvbo); 2153 u8 kind = nouveau_bo_tile_layout(nvbo) >> 8;
2189 if (tile_flags == 0x7a00 || 2154 u8 tile = nvbo->tile_mode;
2190 tile_flags == 0xfe00)
2191 nv_fb->r_dma = NvEvoFB32;
2192 else
2193 if (tile_flags == 0x7000)
2194 nv_fb->r_dma = NvEvoFB16;
2195 else
2196 nv_fb->r_dma = NvEvoVRAM_LP;
2197 2155
2198 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) { 2156 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
2199 NV_ERROR(drm, "framebuffer requires contiguous bo\n"); 2157 NV_ERROR(drm, "framebuffer requires contiguous bo\n");
2200 return -EINVAL; 2158 return -EINVAL;
2201 } 2159 }
2202 2160
2161 if (nv_device(drm->device)->chipset >= 0xc0)
2162 tile >>= 4; /* yep.. */
2163
2203 switch (fb->depth) { 2164 switch (fb->depth) {
2204 case 8: nv_fb->r_format = 0x1e00; break; 2165 case 8: nv_fb->r_format = 0x1e00; break;
2205 case 15: nv_fb->r_format = 0xe900; break; 2166 case 15: nv_fb->r_format = 0xe900; break;
@@ -2212,22 +2173,21 @@ nv50_fb_ctor(struct drm_framebuffer *fb)
2212 return -EINVAL; 2173 return -EINVAL;
2213 } 2174 }
2214 2175
2215 if (nv_device(drm->device)->chipset == 0x50) 2176 if (nv_mclass(disp->core) < NV84_DISP_CLASS) {
2216 nv_fb->r_format |= (tile_flags << 8); 2177 nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
2217 2178 (fb->pitches[0] | 0x00100000);
2218 if (!tile_flags) { 2179 nv_fb->r_format |= kind << 16;
2219 if (nv_device(drm->device)->card_type < NV_D0) 2180 } else
2220 nv_fb->r_pitch = 0x00100000 | fb->pitches[0]; 2181 if (nv_mclass(disp->core) < NVD0_DISP_CLASS) {
2221 else 2182 nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
2222 nv_fb->r_pitch = 0x01000000 | fb->pitches[0]; 2183 (fb->pitches[0] | 0x00100000);
2223 } else { 2184 } else {
2224 u32 mode = nvbo->tile_mode; 2185 nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
2225 if (nv_device(drm->device)->card_type >= NV_C0) 2186 (fb->pitches[0] | 0x01000000);
2226 mode >>= 4;
2227 nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
2228 } 2187 }
2188 nv_fb->r_handle = 0xffff0000 | kind;
2229 2189
2230 return 0; 2190 return nv50_fbdma_init(fb->dev, nv_fb->r_handle, 0, pfb->ram->size, kind);
2231} 2191}
2232 2192
2233/****************************************************************************** 2193/******************************************************************************
@@ -2265,6 +2225,11 @@ void
2265nv50_display_destroy(struct drm_device *dev) 2225nv50_display_destroy(struct drm_device *dev)
2266{ 2226{
2267 struct nv50_disp *disp = nv50_disp(dev); 2227 struct nv50_disp *disp = nv50_disp(dev);
2228 struct nv50_fbdma *fbdma, *fbtmp;
2229
2230 list_for_each_entry_safe(fbdma, fbtmp, &disp->fbdma, head) {
2231 nv50_fbdma_fini(dev, fbdma);
2232 }
2268 2233
2269 nv50_dmac_destroy(disp->core, &disp->mast.base); 2234 nv50_dmac_destroy(disp->core, &disp->mast.base);
2270 2235
@@ -2291,6 +2256,7 @@ nv50_display_create(struct drm_device *dev)
2291 disp = kzalloc(sizeof(*disp), GFP_KERNEL); 2256 disp = kzalloc(sizeof(*disp), GFP_KERNEL);
2292 if (!disp) 2257 if (!disp)
2293 return -ENOMEM; 2258 return -ENOMEM;
2259 INIT_LIST_HEAD(&disp->fbdma);
2294 2260
2295 nouveau_display(dev)->priv = disp; 2261 nouveau_display(dev)->priv = disp;
2296 nouveau_display(dev)->dtor = nv50_display_destroy; 2262 nouveau_display(dev)->dtor = nv50_display_destroy;