1/*	$NetBSD: nouveau_dispnv50_core507d.c,v 1.2 2021/12/18 23:45:32 riastradh Exp $	*/
2
3/*
4 * Copyright 2018 Red Hat Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <sys/cdefs.h>
25__KERNEL_RCSID(0, "$NetBSD: nouveau_dispnv50_core507d.c,v 1.2 2021/12/18 23:45:32 riastradh Exp $");
26
27#include "core.h"
28#include "head.h"
29
30#include <nvif/cl507d.h>
31
32#include "nouveau_bo.h"
33
34void
35core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
36{
37	u32 *push;
38	if ((push = evo_wait(&core->chan, 5))) {
39		if (ntfy) {
40			evo_mthd(push, 0x0084, 1);
41			evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY);
42		}
43		evo_mthd(push, 0x0080, 2);
44		evo_data(push, interlock[NV50_DISP_INTERLOCK_BASE] |
45			       interlock[NV50_DISP_INTERLOCK_OVLY]);
46		evo_data(push, 0x00000000);
47		evo_kick(push, &core->chan);
48	}
49}
50
51int
52core507d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
53			struct nvif_device *device)
54{
55	s64 time = nvif_msec(device, 2000ULL,
56		if (nouveau_bo_rd32(bo, offset / 4))
57			break;
58		usleep_range(1, 2);
59	);
60	return time < 0 ? time : 0;
61}
62
63void
64core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
65{
66	nouveau_bo_wr32(bo, offset / 4, 0x00000000);
67}
68
69void
70core507d_init(struct nv50_core *core)
71{
72	u32 *push;
73	if ((push = evo_wait(&core->chan, 2))) {
74		evo_mthd(push, 0x0088, 1);
75		evo_data(push, core->chan.sync.handle);
76		evo_kick(push, &core->chan);
77	}
78}
79
80static const struct nv50_core_func
81core507d = {
82	.init = core507d_init,
83	.ntfy_init = core507d_ntfy_init,
84	.ntfy_wait_done = core507d_ntfy_wait_done,
85	.update = core507d_update,
86	.head = &head507d,
87	.dac = &dac507d,
88	.sor = &sor507d,
89	.pior = &pior507d,
90};
91
92int
93core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
94	      s32 oclass, struct nv50_core **pcore)
95{
96	struct nv50_disp_core_channel_dma_v0 args = {};
97	struct nv50_disp *disp = nv50_disp(drm->dev);
98	struct nv50_core *core;
99	int ret;
100
101	if (!(core = *pcore = kzalloc(sizeof(*core), GFP_KERNEL)))
102		return -ENOMEM;
103	core->func = func;
104
105	ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
106			       &oclass, 0, &args, sizeof(args),
107			       disp->sync->bo.offset, &core->chan);
108	if (ret) {
109		NV_ERROR(drm, "core%04x allocation failed: %d\n", oclass, ret);
110		return ret;
111	}
112
113	return 0;
114}
115
116int
117core507d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
118{
119	return core507d_new_(&core507d, drm, oclass, pcore);
120}
121