diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 14:10:19 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 15:12:56 -0400 |
commit | 8a42364701d6860e51d53bbcbe3c84fe93816861 (patch) | |
tree | ca75f4ef70396f529f6c0b9209c234acd4e243f5 | |
parent | ab0af559d34b6817768c1720859aef7d7009ee57 (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.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dma.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 282 |
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 | ||
151 | static int | 151 | static int |
152 | nv50_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 | |||
196 | static int | ||
197 | nvc0_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 | |||
238 | static int | ||
239 | nvd0_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 | |||
270 | static int | ||
271 | nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head, | 152 | nv50_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 | ||
2049 | struct nv50_fbdma { | ||
2050 | struct list_head head; | ||
2051 | u32 name; | ||
2052 | }; | ||
2053 | |||
2054 | static void | ||
2055 | nv50_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 | |||
2072 | static int | ||
2073 | nv50_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 | |||
2175 | static void | 2140 | static void |
2176 | nv50_fb_dtor(struct drm_framebuffer *fb) | 2141 | nv50_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 | |||
2265 | nv50_display_destroy(struct drm_device *dev) | 2225 | nv50_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; |