forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/gpu/drm/nouveau/dispnv04/crtc.c
....@@ -22,11 +22,10 @@
2222 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2323 * DEALINGS IN THE SOFTWARE.
2424 */
25
-#include <linux/pm_runtime.h>
26
-
27
-#include <drm/drmP.h>
2825 #include <drm/drm_crtc_helper.h>
26
+#include <drm/drm_fourcc.h>
2927 #include <drm/drm_plane_helper.h>
28
+#include <drm/drm_vblank.h>
3029
3130 #include "nouveau_drv.h"
3231 #include "nouveau_reg.h"
....@@ -40,9 +39,15 @@
4039 #include "nvreg.h"
4140 #include "nouveau_fbcon.h"
4241 #include "disp.h"
42
+#include "nouveau_dma.h"
4343
4444 #include <subdev/bios/pll.h>
4545 #include <subdev/clk.h>
46
+
47
+#include <nvif/push006c.h>
48
+
49
+#include <nvif/event.h>
50
+#include <nvif/cl0046.h>
4651
4752 static int
4853 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
....@@ -605,15 +610,16 @@
605610 nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
606611 {
607612 struct nv04_display *disp = nv04_display(crtc->dev);
608
- struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
613
+ struct drm_framebuffer *fb = crtc->primary->fb;
614
+ struct nouveau_bo *nvbo = nouveau_gem_object(fb->obj[0]);
609615 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
610616 int ret;
611617
612
- ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM, false);
618
+ ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false);
613619 if (ret == 0) {
614620 if (disp->image[nv_crtc->index])
615621 nouveau_bo_unpin(disp->image[nv_crtc->index]);
616
- nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
622
+ nouveau_bo_ref(nvbo, &disp->image[nv_crtc->index]);
617623 }
618624
619625 return ret;
....@@ -755,6 +761,7 @@
755761 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
756762 nouveau_bo_unpin(nv_crtc->cursor.nvbo);
757763 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
764
+ nvif_notify_dtor(&nv_crtc->vblank);
758765 kfree(nv_crtc);
759766 }
760767
....@@ -822,8 +829,8 @@
822829 struct drm_device *dev = crtc->dev;
823830 struct nouveau_drm *drm = nouveau_drm(dev);
824831 struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
832
+ struct nouveau_bo *nvbo;
825833 struct drm_framebuffer *drm_fb;
826
- struct nouveau_framebuffer *fb;
827834 int arb_burst, arb_lwm;
828835
829836 NV_DEBUG(drm, "index %d\n", nv_crtc->index);
....@@ -839,13 +846,12 @@
839846 */
840847 if (atomic) {
841848 drm_fb = passed_fb;
842
- fb = nouveau_framebuffer(passed_fb);
843849 } else {
844850 drm_fb = crtc->primary->fb;
845
- fb = nouveau_framebuffer(crtc->primary->fb);
846851 }
847852
848
- nv_crtc->fb.offset = fb->nvbo->bo.offset;
853
+ nvbo = nouveau_gem_object(drm_fb->obj[0]);
854
+ nv_crtc->fb.offset = nvbo->offset;
849855
850856 if (nv_crtc->lut.depth != drm_fb->format->depth) {
851857 nv_crtc->lut.depth = drm_fb->format->depth;
....@@ -1013,11 +1019,11 @@
10131019 nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
10141020
10151021 nouveau_bo_unmap(cursor);
1016
- nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->bo.offset;
1022
+ nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->offset;
10171023 nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
10181024 nv_crtc->cursor.show(nv_crtc, true);
10191025 out:
1020
- drm_gem_object_put_unlocked(gem);
1026
+ drm_gem_object_put(gem);
10211027 return ret;
10221028 }
10231029
....@@ -1030,50 +1036,213 @@
10301036 return 0;
10311037 }
10321038
1033
-static int
1034
-nouveau_crtc_set_config(struct drm_mode_set *set,
1035
- struct drm_modeset_acquire_ctx *ctx)
1036
-{
1037
- struct drm_device *dev;
1038
- struct nouveau_drm *drm;
1039
- int ret;
1039
+struct nv04_page_flip_state {
1040
+ struct list_head head;
1041
+ struct drm_pending_vblank_event *event;
10401042 struct drm_crtc *crtc;
1041
- bool active = false;
1042
- if (!set || !set->crtc)
1043
+ int bpp, pitch;
1044
+ u64 offset;
1045
+};
1046
+
1047
+static int
1048
+nv04_finish_page_flip(struct nouveau_channel *chan,
1049
+ struct nv04_page_flip_state *ps)
1050
+{
1051
+ struct nouveau_fence_chan *fctx = chan->fence;
1052
+ struct nouveau_drm *drm = chan->drm;
1053
+ struct drm_device *dev = drm->dev;
1054
+ struct nv04_page_flip_state *s;
1055
+ unsigned long flags;
1056
+
1057
+ spin_lock_irqsave(&dev->event_lock, flags);
1058
+
1059
+ if (list_empty(&fctx->flip)) {
1060
+ NV_ERROR(drm, "unexpected pageflip\n");
1061
+ spin_unlock_irqrestore(&dev->event_lock, flags);
10431062 return -EINVAL;
1044
-
1045
- dev = set->crtc->dev;
1046
-
1047
- /* get a pm reference here */
1048
- ret = pm_runtime_get_sync(dev->dev);
1049
- if (ret < 0 && ret != -EACCES)
1050
- return ret;
1051
-
1052
- ret = drm_crtc_helper_set_config(set, ctx);
1053
-
1054
- drm = nouveau_drm(dev);
1055
-
1056
- /* if we get here with no crtcs active then we can drop a reference */
1057
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1058
- if (crtc->enabled)
1059
- active = true;
10601063 }
10611064
1062
- pm_runtime_mark_last_busy(dev->dev);
1063
- /* if we have active crtcs and we don't have a power ref,
1064
- take the current one */
1065
- if (active && !drm->have_disp_power_ref) {
1066
- drm->have_disp_power_ref = true;
1067
- return ret;
1065
+ s = list_first_entry(&fctx->flip, struct nv04_page_flip_state, head);
1066
+ if (s->event) {
1067
+ drm_crtc_arm_vblank_event(s->crtc, s->event);
1068
+ } else {
1069
+ /* Give up ownership of vblank for page-flipped crtc */
1070
+ drm_crtc_vblank_put(s->crtc);
10681071 }
1069
- /* if we have no active crtcs, then drop the power ref
1070
- we got before */
1071
- if (!active && drm->have_disp_power_ref) {
1072
- pm_runtime_put_autosuspend(dev->dev);
1073
- drm->have_disp_power_ref = false;
1072
+
1073
+ list_del(&s->head);
1074
+ if (ps)
1075
+ *ps = *s;
1076
+ kfree(s);
1077
+
1078
+ spin_unlock_irqrestore(&dev->event_lock, flags);
1079
+ return 0;
1080
+}
1081
+
1082
+int
1083
+nv04_flip_complete(struct nvif_notify *notify)
1084
+{
1085
+ struct nouveau_cli *cli = (void *)notify->object->client;
1086
+ struct nouveau_drm *drm = cli->drm;
1087
+ struct nouveau_channel *chan = drm->channel;
1088
+ struct nv04_page_flip_state state;
1089
+
1090
+ if (!nv04_finish_page_flip(chan, &state)) {
1091
+ nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
1092
+ state.offset + state.crtc->y *
1093
+ state.pitch + state.crtc->x *
1094
+ state.bpp / 8);
10741095 }
1075
- /* drop the power reference we got coming in here */
1076
- pm_runtime_put_autosuspend(dev->dev);
1096
+
1097
+ return NVIF_NOTIFY_KEEP;
1098
+}
1099
+
1100
+static int
1101
+nv04_page_flip_emit(struct nouveau_channel *chan,
1102
+ struct nouveau_bo *old_bo,
1103
+ struct nouveau_bo *new_bo,
1104
+ struct nv04_page_flip_state *s,
1105
+ struct nouveau_fence **pfence)
1106
+{
1107
+ struct nouveau_fence_chan *fctx = chan->fence;
1108
+ struct nouveau_drm *drm = chan->drm;
1109
+ struct drm_device *dev = drm->dev;
1110
+ struct nvif_push *push = chan->chan.push;
1111
+ unsigned long flags;
1112
+ int ret;
1113
+
1114
+ /* Queue it to the pending list */
1115
+ spin_lock_irqsave(&dev->event_lock, flags);
1116
+ list_add_tail(&s->head, &fctx->flip);
1117
+ spin_unlock_irqrestore(&dev->event_lock, flags);
1118
+
1119
+ /* Synchronize with the old framebuffer */
1120
+ ret = nouveau_fence_sync(old_bo, chan, false, false);
1121
+ if (ret)
1122
+ goto fail;
1123
+
1124
+ /* Emit the pageflip */
1125
+ ret = PUSH_WAIT(push, 2);
1126
+ if (ret)
1127
+ goto fail;
1128
+
1129
+ PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000);
1130
+ PUSH_KICK(push);
1131
+
1132
+ ret = nouveau_fence_new(chan, false, pfence);
1133
+ if (ret)
1134
+ goto fail;
1135
+
1136
+ return 0;
1137
+fail:
1138
+ spin_lock_irqsave(&dev->event_lock, flags);
1139
+ list_del(&s->head);
1140
+ spin_unlock_irqrestore(&dev->event_lock, flags);
1141
+ return ret;
1142
+}
1143
+
1144
+static int
1145
+nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
1146
+ struct drm_pending_vblank_event *event, u32 flags,
1147
+ struct drm_modeset_acquire_ctx *ctx)
1148
+{
1149
+ const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
1150
+ struct drm_device *dev = crtc->dev;
1151
+ struct nouveau_drm *drm = nouveau_drm(dev);
1152
+ struct drm_framebuffer *old_fb = crtc->primary->fb;
1153
+ struct nouveau_bo *old_bo = nouveau_gem_object(old_fb->obj[0]);
1154
+ struct nouveau_bo *new_bo = nouveau_gem_object(fb->obj[0]);
1155
+ struct nv04_page_flip_state *s;
1156
+ struct nouveau_channel *chan;
1157
+ struct nouveau_cli *cli;
1158
+ struct nouveau_fence *fence;
1159
+ struct nv04_display *dispnv04 = nv04_display(dev);
1160
+ struct nvif_push *push;
1161
+ int head = nouveau_crtc(crtc)->index;
1162
+ int ret;
1163
+
1164
+ chan = drm->channel;
1165
+ if (!chan)
1166
+ return -ENODEV;
1167
+ cli = (void *)chan->user.client;
1168
+ push = chan->chan.push;
1169
+
1170
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
1171
+ if (!s)
1172
+ return -ENOMEM;
1173
+
1174
+ if (new_bo != old_bo) {
1175
+ ret = nouveau_bo_pin(new_bo, NOUVEAU_GEM_DOMAIN_VRAM, true);
1176
+ if (ret)
1177
+ goto fail_free;
1178
+ }
1179
+
1180
+ mutex_lock(&cli->mutex);
1181
+ ret = ttm_bo_reserve(&new_bo->bo, true, false, NULL);
1182
+ if (ret)
1183
+ goto fail_unpin;
1184
+
1185
+ /* synchronise rendering channel with the kernel's channel */
1186
+ ret = nouveau_fence_sync(new_bo, chan, false, true);
1187
+ if (ret) {
1188
+ ttm_bo_unreserve(&new_bo->bo);
1189
+ goto fail_unpin;
1190
+ }
1191
+
1192
+ if (new_bo != old_bo) {
1193
+ ttm_bo_unreserve(&new_bo->bo);
1194
+
1195
+ ret = ttm_bo_reserve(&old_bo->bo, true, false, NULL);
1196
+ if (ret)
1197
+ goto fail_unpin;
1198
+ }
1199
+
1200
+ /* Initialize a page flip struct */
1201
+ *s = (struct nv04_page_flip_state)
1202
+ { { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0],
1203
+ new_bo->offset };
1204
+
1205
+ /* Keep vblanks on during flip, for the target crtc of this flip */
1206
+ drm_crtc_vblank_get(crtc);
1207
+
1208
+ /* Emit a page flip */
1209
+ if (swap_interval) {
1210
+ ret = PUSH_WAIT(push, 8);
1211
+ if (ret)
1212
+ goto fail_unreserve;
1213
+
1214
+ PUSH_NVSQ(push, NV05F, 0x012c, 0);
1215
+ PUSH_NVSQ(push, NV05F, 0x0134, head);
1216
+ PUSH_NVSQ(push, NV05F, 0x0100, 0);
1217
+ PUSH_NVSQ(push, NV05F, 0x0130, 0);
1218
+ }
1219
+
1220
+ nouveau_bo_ref(new_bo, &dispnv04->image[head]);
1221
+
1222
+ ret = nv04_page_flip_emit(chan, old_bo, new_bo, s, &fence);
1223
+ if (ret)
1224
+ goto fail_unreserve;
1225
+ mutex_unlock(&cli->mutex);
1226
+
1227
+ /* Update the crtc struct and cleanup */
1228
+ crtc->primary->fb = fb;
1229
+
1230
+ nouveau_bo_fence(old_bo, fence, false);
1231
+ ttm_bo_unreserve(&old_bo->bo);
1232
+ if (old_bo != new_bo)
1233
+ nouveau_bo_unpin(old_bo);
1234
+ nouveau_fence_unref(&fence);
1235
+ return 0;
1236
+
1237
+fail_unreserve:
1238
+ drm_crtc_vblank_put(crtc);
1239
+ ttm_bo_unreserve(&old_bo->bo);
1240
+fail_unpin:
1241
+ mutex_unlock(&cli->mutex);
1242
+ if (old_bo != new_bo)
1243
+ nouveau_bo_unpin(new_bo);
1244
+fail_free:
1245
+ kfree(s);
10771246 return ret;
10781247 }
10791248
....@@ -1081,9 +1250,12 @@
10811250 .cursor_set = nv04_crtc_cursor_set,
10821251 .cursor_move = nv04_crtc_cursor_move,
10831252 .gamma_set = nv_crtc_gamma_set,
1084
- .set_config = nouveau_crtc_set_config,
1085
- .page_flip = nouveau_crtc_page_flip,
1253
+ .set_config = drm_crtc_helper_set_config,
1254
+ .page_flip = nv04_crtc_page_flip,
10861255 .destroy = nv_crtc_destroy,
1256
+ .enable_vblank = nouveau_display_vblank_enable,
1257
+ .disable_vblank = nouveau_display_vblank_disable,
1258
+ .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
10871259 };
10881260
10891261 static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
....@@ -1094,6 +1266,7 @@
10941266 .mode_set_base = nv04_crtc_mode_set_base,
10951267 .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
10961268 .disable = nv_crtc_disable,
1269
+ .get_scanout_position = nouveau_display_scanoutpos,
10971270 };
10981271
10991272 static const uint32_t modeset_formats[] = {
....@@ -1128,9 +1301,19 @@
11281301 return primary;
11291302 }
11301303
1304
+static int nv04_crtc_vblank_handler(struct nvif_notify *notify)
1305
+{
1306
+ struct nouveau_crtc *nv_crtc =
1307
+ container_of(notify, struct nouveau_crtc, vblank);
1308
+
1309
+ drm_crtc_handle_vblank(&nv_crtc->base);
1310
+ return NVIF_NOTIFY_KEEP;
1311
+}
1312
+
11311313 int
11321314 nv04_crtc_create(struct drm_device *dev, int crtc_num)
11331315 {
1316
+ struct nouveau_display *disp = nouveau_display(dev);
11341317 struct nouveau_crtc *nv_crtc;
11351318 int ret;
11361319
....@@ -1153,10 +1336,11 @@
11531336 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
11541337
11551338 ret = nouveau_bo_new(&nouveau_drm(dev)->client, 64*64*4, 0x100,
1156
- TTM_PL_FLAG_VRAM, 0, 0x0000, NULL, NULL,
1339
+ NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, NULL, NULL,
11571340 &nv_crtc->cursor.nvbo);
11581341 if (!ret) {
1159
- ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, false);
1342
+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo,
1343
+ NOUVEAU_GEM_DOMAIN_VRAM, false);
11601344 if (!ret) {
11611345 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
11621346 if (ret)
....@@ -1168,5 +1352,14 @@
11681352
11691353 nv04_cursor_init(nv_crtc);
11701354
1171
- return 0;
1355
+ ret = nvif_notify_ctor(&disp->disp.object, "kmsVbl", nv04_crtc_vblank_handler,
1356
+ false, NV04_DISP_NTFY_VBLANK,
1357
+ &(struct nvif_notify_head_req_v0) {
1358
+ .head = nv_crtc->index,
1359
+ },
1360
+ sizeof(struct nvif_notify_head_req_v0),
1361
+ sizeof(struct nvif_notify_head_rep_v0),
1362
+ &nv_crtc->vblank);
1363
+
1364
+ return ret;
11721365 }