aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-11-04 03:20:36 -0400
committerBen Skeggs <bskeggs@redhat.com>2016-11-06 23:04:53 -0500
commitea8ee39002a103b5dc81c4c87e32929223b86f64 (patch)
tree90a55001ed3862ca3b28a8b922c8752e9bbed6d3
parenta7ae1561909d27e6104cbc85655f31a962ec8683 (diff)
drm/nouveau/kms/nv50: separate out cursor surface commit
This commit separates the calculation of EVO state from the commit, in order to make the same code useful for atomic modesetting. The legacy interfaces have been wrapped on top of them. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c147
2 files changed, 97 insertions, 51 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index d533a32d5e22..e4e385783b8d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -54,7 +54,6 @@ struct nouveau_crtc {
54 54
55 struct { 55 struct {
56 struct nouveau_bo *nvbo; 56 struct nouveau_bo *nvbo;
57 bool visible;
58 uint32_t offset; 57 uint32_t offset;
59 void (*set_offset)(struct nouveau_crtc *, uint32_t offset); 58 void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
60 void (*set_pos)(struct nouveau_crtc *, int x, int y); 59 void (*set_pos)(struct nouveau_crtc *, int x, int y);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 018f33601e1e..d243042751f0 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -112,6 +112,14 @@ struct nv50_head_atom {
112 } core; 112 } core;
113 113
114 struct { 114 struct {
115 bool visible;
116 u32 handle;
117 u64 offset:40;
118 u8 layout:1;
119 u8 format:1;
120 } curs;
121
122 struct {
115 u8 depth; 123 u8 depth;
116 u8 cpp; 124 u8 cpp;
117 u16 x; 125 u16 x;
@@ -123,6 +131,7 @@ struct nv50_head_atom {
123 union { 131 union {
124 struct { 132 struct {
125 bool core:1; 133 bool core:1;
134 bool curs:1;
126 }; 135 };
127 u8 mask; 136 u8 mask;
128 } clr; 137 } clr;
@@ -130,6 +139,7 @@ struct nv50_head_atom {
130 union { 139 union {
131 struct { 140 struct {
132 bool core:1; 141 bool core:1;
142 bool curs:1;
133 bool view:1; 143 bool view:1;
134 bool mode:1; 144 bool mode:1;
135 }; 145 };
@@ -776,6 +786,62 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
776 * Head 786 * Head
777 *****************************************************************************/ 787 *****************************************************************************/
778static void 788static void
789nv50_head_curs_clr(struct nv50_head *head)
790{
791 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
792 u32 *push;
793 if ((push = evo_wait(core, 4))) {
794 if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
795 evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
796 evo_data(push, 0x05000000);
797 } else
798 if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
799 evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
800 evo_data(push, 0x05000000);
801 evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
802 evo_data(push, 0x00000000);
803 } else {
804 evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
805 evo_data(push, 0x05000000);
806 evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
807 evo_data(push, 0x00000000);
808 }
809 evo_kick(push, core);
810 }
811}
812
813static void
814nv50_head_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
815{
816 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
817 u32 *push;
818 if ((push = evo_wait(core, 5))) {
819 if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) {
820 evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
821 evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
822 (asyh->curs.format << 24));
823 evo_data(push, asyh->curs.offset >> 8);
824 } else
825 if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
826 evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
827 evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
828 (asyh->curs.format << 24));
829 evo_data(push, asyh->curs.offset >> 8);
830 evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
831 evo_data(push, asyh->curs.handle);
832 } else {
833 evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
834 evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
835 (asyh->curs.format << 24));
836 evo_data(push, asyh->curs.offset >> 8);
837 evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
838 evo_data(push, asyh->curs.handle);
839 }
840 evo_kick(push, core);
841 }
842}
843
844static void
779nv50_head_core_clr(struct nv50_head *head) 845nv50_head_core_clr(struct nv50_head *head)
780{ 846{
781 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base; 847 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
@@ -941,6 +1007,8 @@ nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y)
941 nv50_head_lut_clr(head); 1007 nv50_head_lut_clr(head);
942 if (asyh->clr.core && (!asyh->set.core || y)) 1008 if (asyh->clr.core && (!asyh->set.core || y))
943 nv50_head_core_clr(head); 1009 nv50_head_core_clr(head);
1010 if (asyh->clr.curs && (!asyh->set.curs || y))
1011 nv50_head_curs_clr(head);
944} 1012}
945 1013
946static void 1014static void
@@ -949,6 +1017,7 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
949 if (asyh->set.mode ) nv50_head_mode (head, asyh); 1017 if (asyh->set.mode ) nv50_head_mode (head, asyh);
950 if (asyh->set.core ) nv50_head_lut_set (head, asyh); 1018 if (asyh->set.core ) nv50_head_lut_set (head, asyh);
951 if (asyh->set.core ) nv50_head_core_set(head, asyh); 1019 if (asyh->set.core ) nv50_head_core_set(head, asyh);
1020 if (asyh->set.curs ) nv50_head_curs_set(head, asyh);
952} 1021}
953 1022
954static void 1023static void
@@ -1017,7 +1086,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
1017 asyh->core.w = asyh->base.w; 1086 asyh->core.w = asyh->base.w;
1018 asyh->core.h = asyh->base.h; 1087 asyh->core.h = asyh->base.h;
1019 } else 1088 } else
1020 if ((asyh->core.visible = true)) { 1089 if ((asyh->core.visible = asyh->curs.visible)) {
1021 /*XXX: We need to either find some way of having the 1090 /*XXX: We need to either find some way of having the
1022 * primary base layer appear black, while still 1091 * primary base layer appear black, while still
1023 * being able to display the other layers, or we 1092 * being able to display the other layers, or we
@@ -1039,6 +1108,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
1039 asyh->lut.offset = head->base.lut.nvbo->bo.offset; 1108 asyh->lut.offset = head->base.lut.nvbo->bo.offset;
1040 } else { 1109 } else {
1041 asyh->core.visible = false; 1110 asyh->core.visible = false;
1111 asyh->curs.visible = false;
1042 } 1112 }
1043 1113
1044 if (!drm_atomic_crtc_needs_modeset(&asyh->state)) { 1114 if (!drm_atomic_crtc_needs_modeset(&asyh->state)) {
@@ -1049,9 +1119,19 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
1049 if (armh->core.visible) { 1119 if (armh->core.visible) {
1050 asyh->clr.core = true; 1120 asyh->clr.core = true;
1051 } 1121 }
1122
1123 if (asyh->curs.visible) {
1124 if (memcmp(&armh->curs, &asyh->curs, sizeof(asyh->curs)))
1125 asyh->set.curs = true;
1126 } else
1127 if (armh->curs.visible) {
1128 asyh->clr.curs = true;
1129 }
1052 } else { 1130 } else {
1053 asyh->clr.core = armh->core.visible; 1131 asyh->clr.core = armh->core.visible;
1132 asyh->clr.curs = armh->curs.visible;
1054 asyh->set.core = asyh->core.visible; 1133 asyh->set.core = asyh->core.visible;
1134 asyh->set.curs = asyh->curs.visible;
1055 } 1135 }
1056 1136
1057 memcpy(armh, asyh, sizeof(*asyh)); 1137 memcpy(armh, asyh, sizeof(*asyh));
@@ -1304,55 +1384,27 @@ static void
1304nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc) 1384nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
1305{ 1385{
1306 struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); 1386 struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
1307 u32 *push = evo_wait(mast, 16); 1387 struct nv50_head *head = nv50_head(&nv_crtc->base);
1308 if (push) { 1388 struct nv50_head_atom *asyh = &head->asy;
1309 if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) { 1389
1310 evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); 1390 asyh->curs.visible = true;
1311 evo_data(push, 0x85000000); 1391 asyh->curs.handle = mast->base.vram.handle;
1312 evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); 1392 asyh->curs.offset = nv_crtc->cursor.nvbo->bo.offset;
1313 } else 1393 asyh->curs.layout = 1;
1314 if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) { 1394 asyh->curs.format = 1;
1315 evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); 1395 nv50_head_atomic_check(&head->base.base, &asyh->state);
1316 evo_data(push, 0x85000000); 1396 nv50_head_flush_set(head, asyh);
1317 evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
1318 evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
1319 evo_data(push, mast->base.vram.handle);
1320 } else {
1321 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
1322 evo_data(push, 0x85000000);
1323 evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
1324 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
1325 evo_data(push, mast->base.vram.handle);
1326 }
1327 evo_kick(push, mast);
1328 }
1329 nv_crtc->cursor.visible = true;
1330} 1397}
1331 1398
1332static void 1399static void
1333nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc) 1400nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
1334{ 1401{
1335 struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); 1402 struct nv50_head *head = nv50_head(&nv_crtc->base);
1336 u32 *push = evo_wait(mast, 16); 1403 struct nv50_head_atom *asyh = &head->asy;
1337 if (push) { 1404
1338 if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) { 1405 asyh->curs.visible = false;
1339 evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1); 1406 nv50_head_atomic_check(&head->base.base, &asyh->state);
1340 evo_data(push, 0x05000000); 1407 nv50_head_flush_clr(head, asyh, false);
1341 } else
1342 if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
1343 evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
1344 evo_data(push, 0x05000000);
1345 evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
1346 evo_data(push, 0x00000000);
1347 } else {
1348 evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
1349 evo_data(push, 0x05000000);
1350 evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
1351 evo_data(push, 0x00000000);
1352 }
1353 evo_kick(push, mast);
1354 }
1355 nv_crtc->cursor.visible = false;
1356} 1408}
1357 1409
1358static void 1410static void
@@ -1383,7 +1435,6 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
1383static void 1435static void
1384nv50_crtc_prepare(struct drm_crtc *crtc) 1436nv50_crtc_prepare(struct drm_crtc *crtc)
1385{ 1437{
1386 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
1387 struct nv50_head *head = nv50_head(crtc); 1438 struct nv50_head *head = nv50_head(crtc);
1388 struct nv50_head_atom *asyh = &head->asy; 1439 struct nv50_head_atom *asyh = &head->asy;
1389 1440
@@ -1392,14 +1443,11 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
1392 asyh->state.active = false; 1443 asyh->state.active = false;
1393 nv50_head_atomic_check(&head->base.base, &asyh->state); 1444 nv50_head_atomic_check(&head->base.base, &asyh->state);
1394 nv50_head_flush_clr(head, asyh, false); 1445 nv50_head_flush_clr(head, asyh, false);
1395
1396 nv50_crtc_cursor_show_hide(nv_crtc, false, false);
1397} 1446}
1398 1447
1399static void 1448static void
1400nv50_crtc_commit(struct drm_crtc *crtc) 1449nv50_crtc_commit(struct drm_crtc *crtc)
1401{ 1450{
1402 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
1403 struct nv50_head *head = nv50_head(crtc); 1451 struct nv50_head *head = nv50_head(crtc);
1404 struct nv50_head_atom *asyh = &head->asy; 1452 struct nv50_head_atom *asyh = &head->asy;
1405 1453
@@ -1407,7 +1455,6 @@ nv50_crtc_commit(struct drm_crtc *crtc)
1407 nv50_head_atomic_check(&head->base.base, &asyh->state); 1455 nv50_head_atomic_check(&head->base.base, &asyh->state);
1408 nv50_head_flush_set(head, asyh); 1456 nv50_head_flush_set(head, asyh);
1409 1457
1410 nv50_crtc_cursor_show_hide(nv_crtc, true, true);
1411 nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1); 1458 nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
1412} 1459}
1413 1460