1 /*
2  * Copyright 2018 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 #include "wndw.h"
23 #include "atom.h"
24 
25 #include <drm/drm_atomic_helper.h>
26 #include <drm/drm_plane_helper.h>
27 #include <nouveau_bo.h>
28 
29 #include <nvif/clc37e.h>
30 
31 static void
32 wndwc37e_csc_clr(struct nv50_wndw *wndw)
33 {
34 }
35 
36 static void
37 wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
38 {
39 	u32 *push, i;
40 	if ((push = evo_wait(&wndw->wndw, 13))) {
41 		 evo_mthd(push, 0x02bc, 12);
42 		 for (i = 0; i < 12; i++)
43 			  evo_data(push, asyw->csc.matrix[i]);
44 		 evo_kick(push, &wndw->wndw);
45 	}
46 }
47 
48 static void
49 wndwc37e_ilut_clr(struct nv50_wndw *wndw)
50 {
51 	u32 *push;
52 	if ((push = evo_wait(&wndw->wndw, 2))) {
53 		evo_mthd(push, 0x02b8, 1);
54 		evo_data(push, 0x00000000);
55 		evo_kick(push, &wndw->wndw);
56 	}
57 }
58 
59 static void
60 wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
61 {
62 	u32 *push;
63 	if ((push = evo_wait(&wndw->wndw, 4))) {
64 		evo_mthd(push, 0x02b0, 3);
65 		evo_data(push, asyw->xlut.i.output_mode << 8 |
66 			       asyw->xlut.i.range << 4 |
67 			       asyw->xlut.i.size);
68 		evo_data(push, asyw->xlut.i.offset >> 8);
69 		evo_data(push, asyw->xlut.handle);
70 		evo_kick(push, &wndw->wndw);
71 	}
72 }
73 
74 static void
75 wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
76 {
77 	asyw->xlut.i.mode = 2;
78 	asyw->xlut.i.size = 0;
79 	asyw->xlut.i.range = 0;
80 	asyw->xlut.i.output_mode = 1;
81 	asyw->xlut.i.load = head907d_olut_load;
82 }
83 
84 void
85 wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
86 {
87 	u32 *push;
88 	if ((push = evo_wait(&wndw->wndw, 8))) {
89 		evo_mthd(push, 0x02ec, 7);
90 		evo_data(push, asyw->blend.depth << 4);
91 		evo_data(push, asyw->blend.k1);
92 		evo_data(push, asyw->blend.dst_color << 12 |
93 			       asyw->blend.dst_color << 8 |
94 			       asyw->blend.src_color << 4 |
95 			       asyw->blend.src_color);
96 		evo_data(push, 0xffff0000);
97 		evo_data(push, 0xffff0000);
98 		evo_data(push, 0xffff0000);
99 		evo_data(push, 0xffff0000);
100 		evo_kick(push, &wndw->wndw);
101 	}
102 }
103 
104 void
105 wndwc37e_image_clr(struct nv50_wndw *wndw)
106 {
107 	u32 *push;
108 	if ((push = evo_wait(&wndw->wndw, 4))) {
109 		evo_mthd(push, 0x0308, 1);
110 		evo_data(push, 0x00000000);
111 		evo_mthd(push, 0x0240, 1);
112 		evo_data(push, 0x00000000);
113 		evo_kick(push, &wndw->wndw);
114 	}
115 }
116 
117 static void
118 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
119 {
120 	u32 *push;
121 
122 	if (!(push = evo_wait(&wndw->wndw, 17)))
123 		return;
124 
125 	evo_mthd(push, 0x0308, 1);
126 	evo_data(push, asyw->image.mode << 4 | asyw->image.interval);
127 	evo_mthd(push, 0x0224, 4);
128 	evo_data(push, asyw->image.h << 16 | asyw->image.w);
129 	evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
130 	evo_data(push, asyw->csc.valid << 17 |
131 		       asyw->image.colorspace << 8 |
132 		       asyw->image.format);
133 	evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
134 	evo_mthd(push, 0x0240, 1);
135 	evo_data(push, asyw->image.handle[0]);
136 	evo_mthd(push, 0x0260, 1);
137 	evo_data(push, asyw->image.offset[0] >> 8);
138 	evo_mthd(push, 0x0290, 1);
139 	evo_data(push, (asyw->state.src_y >> 16) << 16 |
140 		       (asyw->state.src_x >> 16));
141 	evo_mthd(push, 0x0298, 1);
142 	evo_data(push, (asyw->state.src_h >> 16) << 16 |
143 		       (asyw->state.src_w >> 16));
144 	evo_mthd(push, 0x02a4, 1);
145 	evo_data(push, asyw->state.crtc_h << 16 |
146 		       asyw->state.crtc_w);
147 	evo_kick(push, &wndw->wndw);
148 }
149 
150 void
151 wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
152 {
153 	u32 *push;
154 	if ((push = evo_wait(&wndw->wndw, 2))) {
155 		evo_mthd(push, 0x021c, 1);
156 		evo_data(push, 0x00000000);
157 		evo_kick(push, &wndw->wndw);
158 	}
159 }
160 
161 void
162 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
163 {
164 	u32 *push;
165 	if ((push = evo_wait(&wndw->wndw, 3))) {
166 		evo_mthd(push, 0x021c, 2);
167 		evo_data(push, asyw->ntfy.handle);
168 		evo_data(push, asyw->ntfy.offset | asyw->ntfy.awaken);
169 		evo_kick(push, &wndw->wndw);
170 	}
171 }
172 
173 void
174 wndwc37e_sema_clr(struct nv50_wndw *wndw)
175 {
176 	u32 *push;
177 	if ((push = evo_wait(&wndw->wndw, 2))) {
178 		evo_mthd(push, 0x0218, 1);
179 		evo_data(push, 0x00000000);
180 		evo_kick(push, &wndw->wndw);
181 	}
182 }
183 
184 void
185 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
186 {
187 	u32 *push;
188 	if ((push = evo_wait(&wndw->wndw, 5))) {
189 		evo_mthd(push, 0x020c, 4);
190 		evo_data(push, asyw->sema.offset);
191 		evo_data(push, asyw->sema.acquire);
192 		evo_data(push, asyw->sema.release);
193 		evo_data(push, asyw->sema.handle);
194 		evo_kick(push, &wndw->wndw);
195 	}
196 }
197 
198 void
199 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
200 {
201 	u32 *push;
202 	if ((push = evo_wait(&wndw->wndw, 5))) {
203 		evo_mthd(push, 0x0370, 2);
204 		evo_data(push, interlock[NV50_DISP_INTERLOCK_CURS] << 1 |
205 			       interlock[NV50_DISP_INTERLOCK_CORE]);
206 		evo_data(push, interlock[NV50_DISP_INTERLOCK_WNDW]);
207 		evo_mthd(push, 0x0200, 1);
208 		if (interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data)
209 			evo_data(push, 0x00001001);
210 		else
211 			evo_data(push, 0x00000001);
212 		evo_kick(push, &wndw->wndw);
213 	}
214 }
215 
216 void
217 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
218 		 struct nv50_head_atom *asyh)
219 {
220 }
221 
222 int
223 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
224 		 struct nv50_head_atom *asyh)
225 {
226 	return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
227 						   DRM_PLANE_HELPER_NO_SCALING,
228 						   DRM_PLANE_HELPER_NO_SCALING,
229 						   true, true);
230 }
231 
232 static const u32
233 wndwc37e_format[] = {
234 	DRM_FORMAT_C8,
235 	DRM_FORMAT_YUYV,
236 	DRM_FORMAT_UYVY,
237 	DRM_FORMAT_XRGB8888,
238 	DRM_FORMAT_ARGB8888,
239 	DRM_FORMAT_RGB565,
240 	DRM_FORMAT_XRGB1555,
241 	DRM_FORMAT_ARGB1555,
242 	DRM_FORMAT_XBGR2101010,
243 	DRM_FORMAT_ABGR2101010,
244 	DRM_FORMAT_XBGR8888,
245 	DRM_FORMAT_ABGR8888,
246 	DRM_FORMAT_XRGB2101010,
247 	DRM_FORMAT_ARGB2101010,
248 	DRM_FORMAT_XBGR16161616F,
249 	DRM_FORMAT_ABGR16161616F,
250 	0
251 };
252 
253 static const struct nv50_wndw_func
254 wndwc37e = {
255 	.acquire = wndwc37e_acquire,
256 	.release = wndwc37e_release,
257 	.sema_set = wndwc37e_sema_set,
258 	.sema_clr = wndwc37e_sema_clr,
259 	.ntfy_set = wndwc37e_ntfy_set,
260 	.ntfy_clr = wndwc37e_ntfy_clr,
261 	.ntfy_reset = corec37d_ntfy_init,
262 	.ntfy_wait_begun = base507c_ntfy_wait_begun,
263 	.ilut = wndwc37e_ilut,
264 	.xlut_set = wndwc37e_ilut_set,
265 	.xlut_clr = wndwc37e_ilut_clr,
266 	.csc = base907c_csc,
267 	.csc_set = wndwc37e_csc_set,
268 	.csc_clr = wndwc37e_csc_clr,
269 	.image_set = wndwc37e_image_set,
270 	.image_clr = wndwc37e_image_clr,
271 	.blend_set = wndwc37e_blend_set,
272 	.update = wndwc37e_update,
273 };
274 
275 int
276 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
277 	      enum drm_plane_type type, int index, s32 oclass, u32 heads,
278 	      struct nv50_wndw **pwndw)
279 {
280 	struct nvc37e_window_channel_dma_v0 args = {
281 		.pushbuf = 0xb0007e00 | index,
282 		.index = index,
283 	};
284 	struct nv50_disp *disp = nv50_disp(drm->dev);
285 	struct nv50_wndw *wndw;
286 	int ret;
287 
288 	ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index,
289 			     wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW,
290 			     BIT(index), &wndw);
291 	if (*pwndw = wndw, ret)
292 		return ret;
293 
294 	ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
295 			       &oclass, 0, &args, sizeof(args),
296 			       disp->sync->bo.offset, &wndw->wndw);
297 	if (ret) {
298 		NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret);
299 		return ret;
300 	}
301 
302 	wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id);
303 	wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id);
304 	wndw->data = 0x00000000;
305 	return 0;
306 }
307 
308 int
309 wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
310 	     s32 oclass, struct nv50_wndw **pwndw)
311 {
312 	return wndwc37e_new_(&wndwc37e, drm, type, index, oclass,
313 			     BIT(index >> 1), pwndw);
314 }
315