drm/nouveau/kms/nv50-: convert wndw image_set() to new push macros
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / dispnv50 / wndwc37e.c
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 #include <nvif/pushc37b.h>
31
32 static int
33 wndwc37e_csc_clr(struct nv50_wndw *wndw)
34 {
35         return 0;
36 }
37
38 static int
39 wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
40 {
41         struct nvif_push *push = wndw->wndw.push;
42         int ret;
43
44         if ((ret = PUSH_WAIT(push, 13)))
45                 return ret;
46
47         PUSH_NVSQ(push, NVC37E, 0x02bc, asyw->csc.matrix, 12);
48         return 0;
49 }
50
51 static int
52 wndwc37e_ilut_clr(struct nv50_wndw *wndw)
53 {
54         struct nvif_push *push = wndw->wndw.push;
55         int ret;
56
57         if ((ret = PUSH_WAIT(push, 2)))
58                 return ret;
59
60         PUSH_NVSQ(push, NVC37E, 0x02b8, 0x00000000);
61         return 0;
62 }
63
64 static int
65 wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
66 {
67         struct nvif_push *push = wndw->wndw.push;
68         int ret;
69
70         if ((ret = PUSH_WAIT(push, 4)))
71                 return ret;
72
73         PUSH_NVSQ(push, NVC37E, 0x02b0, asyw->xlut.i.output_mode << 8 |
74                                         asyw->xlut.i.range << 4 |
75                                         asyw->xlut.i.size,
76                                 0x02b4, asyw->xlut.i.offset >> 8,
77                                 0x02b8, asyw->xlut.handle);
78         return 0;
79 }
80
81 static bool
82 wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
83 {
84         if (size != 256 && size != 1024)
85                 return false;
86
87         asyw->xlut.i.mode = 2;
88         asyw->xlut.i.size = size == 1024 ? 2 : 0;
89         asyw->xlut.i.range = 0;
90         asyw->xlut.i.output_mode = 1;
91         asyw->xlut.i.load = head907d_olut_load;
92         return true;
93 }
94
95 void
96 wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
97 {
98         u32 *push;
99         if ((push = evo_wait(&wndw->wndw, 8))) {
100                 evo_mthd(push, 0x02ec, 7);
101                 evo_data(push, asyw->blend.depth << 4);
102                 evo_data(push, asyw->blend.k1);
103                 evo_data(push, asyw->blend.dst_color << 12 |
104                                asyw->blend.dst_color << 8 |
105                                asyw->blend.src_color << 4 |
106                                asyw->blend.src_color);
107                 evo_data(push, 0xffff0000);
108                 evo_data(push, 0xffff0000);
109                 evo_data(push, 0xffff0000);
110                 evo_data(push, 0xffff0000);
111                 evo_kick(push, &wndw->wndw);
112         }
113 }
114
115 void
116 wndwc37e_image_clr(struct nv50_wndw *wndw)
117 {
118         u32 *push;
119         if ((push = evo_wait(&wndw->wndw, 4))) {
120                 evo_mthd(push, 0x0308, 1);
121                 evo_data(push, 0x00000000);
122                 evo_mthd(push, 0x0240, 1);
123                 evo_data(push, 0x00000000);
124                 evo_kick(push, &wndw->wndw);
125         }
126 }
127
128 static int
129 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
130 {
131         struct nvif_push *push = wndw->wndw.push;
132         int ret;
133
134         if ((ret = PUSH_WAIT(push, 17)))
135                 return ret;
136
137         PUSH_NVSQ(push, NVC37E, 0x0308, asyw->image.mode << 4 |
138                                         asyw->image.interval);
139         PUSH_NVSQ(push, NVC37E, 0x0224, asyw->image.h << 16 | asyw->image.w,
140                                 0x0228, asyw->image.layout << 4 |
141                                         asyw->image.blockh,
142                                 0x022c, asyw->csc.valid << 17 |
143                                         asyw->image.colorspace << 8 |
144                                         asyw->image.format,
145                                 0x0230, asyw->image.blocks[0] |
146                                        (asyw->image.pitch[0] >> 6));
147         PUSH_NVSQ(push, NVC37E, 0x0240, asyw->image.handle[0]);
148         PUSH_NVSQ(push, NVC37E, 0x0260, asyw->image.offset[0] >> 8);
149         PUSH_NVSQ(push, NVC37E, 0x0290,(asyw->state.src_y >> 16) << 16 |
150                                        (asyw->state.src_x >> 16));
151         PUSH_NVSQ(push, NVC37E, 0x0298,(asyw->state.src_h >> 16) << 16 |
152                                        (asyw->state.src_w >> 16));
153         PUSH_NVSQ(push, NVC37E, 0x02a4, asyw->state.crtc_h << 16 |
154                                         asyw->state.crtc_w);
155         return 0;
156 }
157
158 int
159 wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
160 {
161         struct nvif_push *push = wndw->wndw.push;
162         int ret;
163
164         if ((ret = PUSH_WAIT(push, 2)))
165                 return ret;
166
167         PUSH_NVSQ(push, NVC37E, 0x021c, 0x00000000);
168         return 0;
169 }
170
171 int
172 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
173 {
174         struct nvif_push *push = wndw->wndw.push;
175         int ret;
176
177         if ((ret = PUSH_WAIT(push, 3)))
178                 return ret;
179
180         PUSH_NVSQ(push, NVC37E, 0x021c, asyw->ntfy.handle,
181                                 0x0220, asyw->ntfy.offset |
182                                         asyw->ntfy.awaken);
183         return 0;
184 }
185
186 int
187 wndwc37e_sema_clr(struct nv50_wndw *wndw)
188 {
189         struct nvif_push *push = wndw->wndw.push;
190         int ret;
191
192         if ((ret = PUSH_WAIT(push, 2)))
193                 return ret;
194
195         PUSH_NVSQ(push, NVC37E, 0x0218, 0x00000000);
196         return 0;
197 }
198
199 int
200 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
201 {
202         struct nvif_push *push = wndw->wndw.push;
203         int ret;
204
205         if ((ret = PUSH_WAIT(push, 5)))
206                 return ret;
207
208         PUSH_NVSQ(push, NVC37E, 0x020c, asyw->sema.offset,
209                                 0x0210, asyw->sema.acquire,
210                                 0x0214, asyw->sema.release,
211                                 0x0218, asyw->sema.handle);
212         return 0;
213 }
214
215 void
216 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
217 {
218         u32 *push;
219         if ((push = evo_wait(&wndw->wndw, 5))) {
220                 evo_mthd(push, 0x0370, 2);
221                 evo_data(push, interlock[NV50_DISP_INTERLOCK_CURS] << 1 |
222                                interlock[NV50_DISP_INTERLOCK_CORE]);
223                 evo_data(push, interlock[NV50_DISP_INTERLOCK_WNDW]);
224                 evo_mthd(push, 0x0200, 1);
225                 if (interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data)
226                         evo_data(push, 0x00001001);
227                 else
228                         evo_data(push, 0x00000001);
229                 evo_kick(push, &wndw->wndw);
230         }
231 }
232
233 void
234 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
235                  struct nv50_head_atom *asyh)
236 {
237 }
238
239 int
240 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
241                  struct nv50_head_atom *asyh)
242 {
243         return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
244                                                    DRM_PLANE_HELPER_NO_SCALING,
245                                                    DRM_PLANE_HELPER_NO_SCALING,
246                                                    true, true);
247 }
248
249 static const u32
250 wndwc37e_format[] = {
251         DRM_FORMAT_C8,
252         DRM_FORMAT_YUYV,
253         DRM_FORMAT_UYVY,
254         DRM_FORMAT_XRGB8888,
255         DRM_FORMAT_ARGB8888,
256         DRM_FORMAT_RGB565,
257         DRM_FORMAT_XRGB1555,
258         DRM_FORMAT_ARGB1555,
259         DRM_FORMAT_XBGR2101010,
260         DRM_FORMAT_ABGR2101010,
261         DRM_FORMAT_XBGR8888,
262         DRM_FORMAT_ABGR8888,
263         DRM_FORMAT_XRGB2101010,
264         DRM_FORMAT_ARGB2101010,
265         DRM_FORMAT_XBGR16161616F,
266         DRM_FORMAT_ABGR16161616F,
267         0
268 };
269
270 static const struct nv50_wndw_func
271 wndwc37e = {
272         .acquire = wndwc37e_acquire,
273         .release = wndwc37e_release,
274         .sema_set = wndwc37e_sema_set,
275         .sema_clr = wndwc37e_sema_clr,
276         .ntfy_set = wndwc37e_ntfy_set,
277         .ntfy_clr = wndwc37e_ntfy_clr,
278         .ntfy_reset = corec37d_ntfy_init,
279         .ntfy_wait_begun = base507c_ntfy_wait_begun,
280         .ilut = wndwc37e_ilut,
281         .ilut_size = 1024,
282         .xlut_set = wndwc37e_ilut_set,
283         .xlut_clr = wndwc37e_ilut_clr,
284         .csc = base907c_csc,
285         .csc_set = wndwc37e_csc_set,
286         .csc_clr = wndwc37e_csc_clr,
287         .image_set = wndwc37e_image_set,
288         .image_clr = wndwc37e_image_clr,
289         .blend_set = wndwc37e_blend_set,
290         .update = wndwc37e_update,
291 };
292
293 int
294 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
295               enum drm_plane_type type, int index, s32 oclass, u32 heads,
296               struct nv50_wndw **pwndw)
297 {
298         struct nvc37e_window_channel_dma_v0 args = {
299                 .pushbuf = 0xb0007e00 | index,
300                 .index = index,
301         };
302         struct nv50_disp *disp = nv50_disp(drm->dev);
303         struct nv50_wndw *wndw;
304         int ret;
305
306         ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index,
307                              wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW,
308                              BIT(index), &wndw);
309         if (*pwndw = wndw, ret)
310                 return ret;
311
312         ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
313                                &oclass, 0, &args, sizeof(args),
314                                disp->sync->offset, &wndw->wndw);
315         if (ret) {
316                 NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret);
317                 return ret;
318         }
319
320         wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id);
321         wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id);
322         wndw->data = 0x00000000;
323         return 0;
324 }
325
326 int
327 wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
328              s32 oclass, struct nv50_wndw **pwndw)
329 {
330         return wndwc37e_new_(&wndwc37e, drm, type, index, oclass,
331                              BIT(index >> 1), pwndw);
332 }