11590700dSBen Skeggs /*
21590700dSBen Skeggs  * Copyright 2018 Red Hat Inc.
31590700dSBen Skeggs  *
41590700dSBen Skeggs  * Permission is hereby granted, free of charge, to any person obtaining a
51590700dSBen Skeggs  * copy of this software and associated documentation files (the "Software"),
61590700dSBen Skeggs  * to deal in the Software without restriction, including without limitation
71590700dSBen Skeggs  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81590700dSBen Skeggs  * and/or sell copies of the Software, and to permit persons to whom the
91590700dSBen Skeggs  * Software is furnished to do so, subject to the following conditions:
101590700dSBen Skeggs  *
111590700dSBen Skeggs  * The above copyright notice and this permission notice shall be included in
121590700dSBen Skeggs  * all copies or substantial portions of the Software.
131590700dSBen Skeggs  *
141590700dSBen Skeggs  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151590700dSBen Skeggs  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
161590700dSBen Skeggs  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
171590700dSBen Skeggs  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
181590700dSBen Skeggs  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191590700dSBen Skeggs  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201590700dSBen Skeggs  * OTHER DEALINGS IN THE SOFTWARE.
211590700dSBen Skeggs  */
221590700dSBen Skeggs #include "core.h"
231590700dSBen Skeggs #include "head.h"
241590700dSBen Skeggs 
251590700dSBen Skeggs #include <nvif/cl507d.h>
265e691222SBen Skeggs #include <nvif/push507c.h>
27ed3d1489SBen Skeggs #include <nvif/timer.h>
281590700dSBen Skeggs 
29b11d8ca1SBen Skeggs #include <nvhw/class/cl507d.h>
30b11d8ca1SBen Skeggs 
311590700dSBen Skeggs #include "nouveau_bo.h"
321590700dSBen Skeggs 
33203f6eafSBen Skeggs int
3453e0a3e7SBen Skeggs core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
3509e1b78aSBen Skeggs {
36203f6eafSBen Skeggs 	struct nvif_push *push = core->chan.push;
37203f6eafSBen Skeggs 	int ret;
38203f6eafSBen Skeggs 
39203f6eafSBen Skeggs 	if ((ret = PUSH_WAIT(push, 5)))
40203f6eafSBen Skeggs 		return ret;
41203f6eafSBen Skeggs 
42203f6eafSBen Skeggs 	if (ntfy)
43203f6eafSBen Skeggs 		PUSH_NVSQ(push, NV507D, 0x0084, 0x80000000 | NV50_DISP_CORE_NTFY);
44203f6eafSBen Skeggs 
45203f6eafSBen Skeggs 	PUSH_NVSQ(push, NV507D, 0x0080, interlock[NV50_DISP_INTERLOCK_BASE] |
46203f6eafSBen Skeggs 					interlock[NV50_DISP_INTERLOCK_OVLY],
47203f6eafSBen Skeggs 				0x0084, 0x00000000);
48203f6eafSBen Skeggs 	return PUSH_KICK(push);
4909e1b78aSBen Skeggs }
5009e1b78aSBen Skeggs 
5109e1b78aSBen Skeggs int
5209e1b78aSBen Skeggs core507d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
5309e1b78aSBen Skeggs 			struct nvif_device *device)
5409e1b78aSBen Skeggs {
5509e1b78aSBen Skeggs 	s64 time = nvif_msec(device, 2000ULL,
564daef27cSBen Skeggs 		if (NVBO_TD32(bo, offset, NV_DISP_CORE_NOTIFIER_1, COMPLETION_0, DONE, ==, TRUE))
5709e1b78aSBen Skeggs 			break;
5809e1b78aSBen Skeggs 		usleep_range(1, 2);
5909e1b78aSBen Skeggs 	);
6009e1b78aSBen Skeggs 	return time < 0 ? time : 0;
6109e1b78aSBen Skeggs }
6209e1b78aSBen Skeggs 
6309e1b78aSBen Skeggs void
6409e1b78aSBen Skeggs core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
6509e1b78aSBen Skeggs {
6638a323b0SBen Skeggs 	NVBO_WR32(bo, offset, NV_DISP_CORE_NOTIFIER_1, COMPLETION_0,
6738a323b0SBen Skeggs 			NVDEF(NV_DISP_CORE_NOTIFIER_1, COMPLETION_0, DONE, FALSE));
6809e1b78aSBen Skeggs }
6909e1b78aSBen Skeggs 
704a2cb418SLyude Paul int
714a2cb418SLyude Paul core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
724a2cb418SLyude Paul {
733c43c362SBen Skeggs 	struct nvif_push *push = disp->core->chan.push;
743c43c362SBen Skeggs 	int ret;
754a2cb418SLyude Paul 
763c43c362SBen Skeggs 	if ((ret = PUSH_WAIT(push, 2)))
773c43c362SBen Skeggs 		return ret;
784a2cb418SLyude Paul 
79d8b24526SBen Skeggs 	PUSH_MTHD(push, NV507D, GET_CAPABILITIES, 0x00000000);
803c43c362SBen Skeggs 	return PUSH_KICK(push);
814a2cb418SLyude Paul }
824a2cb418SLyude Paul 
835e691222SBen Skeggs int
8409e1b78aSBen Skeggs core507d_init(struct nv50_core *core)
8509e1b78aSBen Skeggs {
865e691222SBen Skeggs 	struct nvif_push *push = core->chan.push;
875e691222SBen Skeggs 	int ret;
885e691222SBen Skeggs 
895e691222SBen Skeggs 	if ((ret = PUSH_WAIT(push, 2)))
905e691222SBen Skeggs 		return ret;
915e691222SBen Skeggs 
92b11d8ca1SBen Skeggs 	PUSH_MTHD(push, NV507D, SET_CONTEXT_DMA_NOTIFIER, core->chan.sync.handle);
935e691222SBen Skeggs 	return PUSH_KICK(push);
9409e1b78aSBen Skeggs }
9509e1b78aSBen Skeggs 
961590700dSBen Skeggs static const struct nv50_core_func
971590700dSBen Skeggs core507d = {
9809e1b78aSBen Skeggs 	.init = core507d_init,
9909e1b78aSBen Skeggs 	.ntfy_init = core507d_ntfy_init,
1004a2cb418SLyude Paul 	.caps_init = core507d_caps_init,
10109e1b78aSBen Skeggs 	.ntfy_wait_done = core507d_ntfy_wait_done,
10209e1b78aSBen Skeggs 	.update = core507d_update,
1031590700dSBen Skeggs 	.head = &head507d,
1041590700dSBen Skeggs 	.dac = &dac507d,
1051590700dSBen Skeggs 	.sor = &sor507d,
1061590700dSBen Skeggs 	.pior = &pior507d,
1071590700dSBen Skeggs };
1081590700dSBen Skeggs 
10909e1b78aSBen Skeggs int
1101590700dSBen Skeggs core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
1111590700dSBen Skeggs 	      s32 oclass, struct nv50_core **pcore)
1121590700dSBen Skeggs {
1131590700dSBen Skeggs 	struct nv50_disp_core_channel_dma_v0 args = {};
1141590700dSBen Skeggs 	struct nv50_disp *disp = nv50_disp(drm->dev);
1151590700dSBen Skeggs 	struct nv50_core *core;
1161590700dSBen Skeggs 	int ret;
1171590700dSBen Skeggs 
1181590700dSBen Skeggs 	if (!(core = *pcore = kzalloc(sizeof(*core), GFP_KERNEL)))
1191590700dSBen Skeggs 		return -ENOMEM;
1201590700dSBen Skeggs 	core->func = func;
1211590700dSBen Skeggs 
1221590700dSBen Skeggs 	ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
1231590700dSBen Skeggs 			       &oclass, 0, &args, sizeof(args),
1240dc9b286SNirmoy Das 			       disp->sync->offset, &core->chan);
1251590700dSBen Skeggs 	if (ret) {
1261590700dSBen Skeggs 		NV_ERROR(drm, "core%04x allocation failed: %d\n", oclass, ret);
1271590700dSBen Skeggs 		return ret;
1281590700dSBen Skeggs 	}
1291590700dSBen Skeggs 
1301590700dSBen Skeggs 	return 0;
1311590700dSBen Skeggs }
1321590700dSBen Skeggs 
1331590700dSBen Skeggs int
1341590700dSBen Skeggs core507d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
1351590700dSBen Skeggs {
1361590700dSBen Skeggs 	return core507d_new_(&core507d, drm, oclass, pcore);
1371590700dSBen Skeggs }
138